当前位置: 首页 > news >正文

Vite+Vue3学习笔记(2)——语法、渲染、事件、数据传递、生命周期、第三方库、前端部署

官网链接:https://cn.vuejs.org/

在这里插入图片描述

如果出现普通用户无法新建项目,必须要管理员身份新建,那么可以在nodejs的安装路径设置安全选项,提高普通用户的权限。
具体方法参考:

https://blog.csdn.net/weixin_43174650/article/details/121865934

0 基本标签

标签功能
template模板
div
h1~h6标题
p文字
header头部
main主体
button按钮
img图片
canvas画布
ul无序列表
ol有序列表
li列表项目,用在ul和ol中
input输入文本框
textarea文本区域
select下拉选择框

1 模板语法

首先来看一下项目的结构,src下存放了需要我们关注的文件。

  • assets下包含了静态资源,包括图片和公共的css文件。
  • components下存放vue的组件。
  • App.vue是根组件。
  • main.js是主入口文件。

在这里插入图片描述

1.2 文本

数据绑定,形成能改变的动态文字。使用双花括号{{ }}插入文字。

<template><p>{{ message }}</p>
</template><script>export default {data() {return {message:"学习Vue"}}}
</script>

1.3 链接

双花括号会将数据解释为普通文本,而不是HTML代码。为了输出真正的HTML代码,需要使用v-html代码。

<template><div>{{rawHtml}}</div><div v-html="rawHtml"></div>
</template><script>export default {data() {return {rawHtml:"<a href='https://www.baidu.com'>百度搜索</a>"}}}
</script>

在这里插入图片描述

1.4 属性(attribute)

位于尖角括号内的<*** class="text" width="100px" height="200px">,为标签的属性。

要让属性(class或id)成为能按照js改变的属性,需要使用v-bind指令。

<template><div v-bind:id="dynamicID"></div>
</template><script>
export default{data(){return{dynamicID:10001,}}
</script>

注意:v-bind:可以简写为:

1.5 表达式

只能单行表达式!
赋值语句不可以,if表达式也不可以。

<template><p>输入:{{ num }},输出:{{ num + 10 }}</p><p>{{ flag ? "真":"假" }}</p>
</template><script>export default{data(){return{flag : true,num:10,}}}
</script>

在这里插入图片描述

2 渲染方式

2.1 条件渲染:v-if和v-else

使用变量flag的true和false来控制是否渲染此对象。v-if后面可以紧跟着v-else来表达另外一种选择时的渲染对象。

<template><p v-if="flag">Hello World!</p><p v-else>I am Jonathan!</p>
</template><script>export default{data(){return{flag : true,}}}
</script>

2.2 v-show

只能控制一个,要么显示要么不显示。

<template><p v-show="flag">Hello World!</p>
</template><script>export default{data(){return{flag : true,}}}
</script>

两者的区别:
v-if是真正的条件渲染,没有被渲染的会背销毁,重新渲染的会重建。是惰性的,有更高的切换开销。
v-show只是显示不显示的问题,所有都被渲染,有最高的初始渲染那开销。

2.3 列表渲染:v-for

把一个数组映射为一组元素,然后渲染。
维护模式,添加:key="id"确定一个唯一的标识,以便后期渲染时,只渲染新增的元素,以节约渲染开销。

<template><ul><li v-for="news in newslist" :key="news.id">{{ news.title }}</li></ul>
</template><script>export default{data(){return{newslist:[{id:1001,title:"今日新闻1"},{id:1002,title:"今日新闻2"},{id:1003,title:"今日新闻3"},{id:1004,title:"今日新闻4"},}}}
</script>

在这里里插入图片描述

3 事件处理

3.1 监听事件:v-on或@

使用v-on或者@来监听DOM事件,并在触发事件时执行一些Javascript。用法为:v-on:lick="methodName"或者使用快捷方式@click="methodName"

3.1.1简单事件处理

直接在click事件中添加变量自增。

<template><button @click="counter += 1">点击增加counter值:{{ counter }}</button>
</template><script>export default{data(){return{counter:0,}}}
</script>

在这里插入图片描述

3.1.2 事件处理方法

如果事件处理逻辑较为复杂,则v-on接收一个需要调用的方法(函数)名称。

<template><button @click="clickHandle">点击弹出对话框</button>
</template><script>export default{methods:{clickHandle(){alert("只因你太美!");},}}
</script>

在这里插入图片描述

3.1.3 获取、修改页面信息

获取页面中的数据需要使用this.来指定对象。
event时间内有较多参数,也可以修改。

<template><p>{{ message }}</p><button @click="changeText">撤回消息</button>
</template><script>export default{data(){return{message:"消息通知",}},methods:{changeText(event){// 在时间中,读取data中的属性,是需要通过this.属性this.message = "消息被撤回了。";console.log(event);   //event为原生DOM eventevent.target.innerText = "无新消息";},}}
</script>

在这里插入图片描述

3.1.4 事件传递参数

click可以传递参数到js内。
1、点击按钮传递参数:

<template><p>----------------</p><button @click="sendParam('hi')">send hi</button><button @click="sendParam('bye')">send bye</button>
</template><script>
export default{methods:{sendParam(data){console.log(data);},}
}
</script>

点击按钮可以发现参数传递成功,调试输出了对应文本。

在这里插入图片描述
2、点击文本/列表传递参数

<template><ul><li @click="clickItemHandler(name)" v-for="(name,index) in namelist" :key="index">{{ name }}</li></ul>
</template><script>
export default{data(){return{namelist:['owen','john','frank'],}},methods:{clickItemHandler(name_param){console.log(name_param)},}
}
</script>

点击无序列表的各个项目,可以发现下方调试面板输出了对应的name。

在这里插入图片描述

4 表单输入绑定

4.1 数据绑定v-model

可以使用v-model指令在表单<input><textarea><select>元素上穿件双向数据绑定,该指令会根据控件类型自动选取正确的方法来更新元素。
<input>为输入文本框,只有左半个标签,无</input>

<template><input type="text" v-model="username"><input type="text" v-model="password"><button @click="logIn">登录</button>
</template><script>
export default{data(){return{username:'',password:'',}},methods:{logIn(){console.log('username:' + this.username + ' ,password:' + this.password);console.log();},}
}
</script>

输入用户名和密码,点击登录,可以看到调试界面出现对应数据。
在这里插入图片描述

4.2 修饰符

4.2.1 lazy

在默认情况下,v-model在每次input事件触发后将输入框的值与数据进行同步。如果添加lazy修饰符,将会转化为在change事件之后进行同步(比如输入回车、鼠标点击其他位置)。

<template><input type="text" v-model.lazy="username"><input type="text" v-model="password"><p>{{ username }},{{ password }}</p>
</template><script>
export default{data(){return{username:'',password:'',}},
}
</script>

输入两个文本框,可以发现下方文字不同的输出效果。
在这里插入图片描述

4.2.2 trim

自动过滤用户输入的首尾空白字符。

<template><input type="text" v-model.trim="textBox"><p>{{ textBox }}</p>
</template><script>
export default{data(){return{textBox:'',}},
}
</script>

前后的空格都被过滤,中间的空格没有过滤。
在这里插入图片描述

5 组件基础

5.1 单文件组件

Vue单文件组件,文件后缀是.vue,是一种特殊的文件格式,运行将Vue组件的模板、逻辑与样式封装在单个文件中。

  • template:模板部分,相当于html
  • script:逻辑部分,相当于js。规范编程的话需要在export default内指定组件的name
  • style:样式部分,相当于css。如果添加scoped,则表示当前样式只在该组件内部生效,外部不生效。
//文件名:MyComponent.vue
<template><h1>单文件组件</h1>
</template><script>
export default{name:"MyComponent"
}
</script><style scoped>
h1{color:red;
}
</style>

5.2 加载组件

(1)<script>内引入组件:import MyComponent from './components/MyComponent.vue'
(2)<script>内挂载组件:components: { MyComponent }
(3)<template>内显示组件:<MyComponent /><my-component />

注意:<script setup> </script>可以在<template>之前,如果这样的话,就不用第二步挂载组件了,但引入其他组件时,export default会报错。

在根组件App.vue内引用MyComponent.vue:

<script setup>
import HelloWorld from './components/HelloWorld.vue';
import TheWelcome from './components/TheWelcome.vue';
</script><template><header><img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" /><div class="wrapper"><MyComponent />		//此处显示组件<HelloWorld /></div></header><main><TheWelcome /></main>
</template><script>		// 此处引入组件,挂载组件
import MyComponent from './components/MyComponent.vue';
export default{components:{MyComponent}
}
</script>

在这里插入图片描述

5.3 组件组织关系

通常一个应用会以一棵嵌套的组件树的形式来组织。
在这里插入图片描述

6 样式style

<template class="styleName"> </template>class能够引用样式。
<style>中能够使用的样式种类:

名称功能
border设置边框(线性、宽度、颜色、圆角)
width宽度
height高度
color字体颜色
background背景(颜色、图片、位置)
font字型(字体、字号、加粗、斜体)
text文本(居中、行高、溢出内容处理)
margin外边距(上下左右)
padding内边距

参考网址:https://www.jianshu.com/p/ee736030239b

7 Props的组件交互

组件之间的数据存在交互,有传递数据的方式。

7.1 正向数据传递

prop是可以在组件上注册一些自定义的属性(attribute)。可以从父组件传递到子组件。

prop可以传递的类型:

名称Typedefault
字符串String“”
数字Number0,任何数字
布尔类型Booleantrue或者false
数组Arrayfunction() { return [] }
对象Objectfunction() { return [] }
函数Function

数组和对象必须使用函数进行返回

  • 传出内容的模板需要:
<MyComponent :param1_in="param1" :param2_in="param2"/>
  • 传入的模板需要:
props:{param1_in:{type:String,default:"",},param2_in:{type:Number,default:0,}
}

完整交互过程如下:

//App.vue
<template><img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" /><div class="wrapper"><MyComponent :titleMC="title" :yearMC="year" :monthMC="month"/>	//此处传入的是内容<HelloWorld/><TheWelcome /></div></template><script>
import HelloWorld from './components/HelloWorld.vue';
import TheWelcome from './components/TheWelcome.vue';
import MyComponent from './components/MyComponent.vue';
export default{name:'App',data(){return{title:'我是一个标题',		//此处定义传入数据year:2023,}},components:{HelloWorld,TheWelcome,MyComponent}
}
</script>

注意:

  • 不加:传递的是固定的字符串,<MyComponent title="title"/>
  • :传递的是内容<MyComponent :title="title"/>
//MyComponent.vue
<template><h1>单文件组件</h1><h3>prop传递数据</h3><p>{{ titleMC }}</p>		//传入数据显示<p>{{ yearMC }}</p><ul><li v-for="(item,index) in monthMC" :key="index">{{ item }}</li></ul>
</template><script>
export default{name:"MyComponent",props:{						//props固定格式titleMC:{				//传入的变量名type:String,		//传入的数据类型default:"未传入值的情况下的默认值",		//默认值},yearMC:{type:Number,default:1997,},monthMC:{type:Array,default:function(){return []}}},
}
</script>

在这里插入图片描述

7.2 自定义事件组件交互——反向传递数据

自定义事件可以在组件中反向传递数据,用$emit实现。
在子组件和父组件中需要构建两个methods:

  • 子组件在触发事件后的函数内使用this.$emit传递eventName和需要传递的数据。
  • 父组件监听eventName,并接入一个新函数来处理这个事件。

子组件示例:

// MyComponent.vue
<template><button @click="sendClickHandle">点击反向传递</button>
</template><script>
export default{name:"MyComponent",data(){return{message:"我是MyComponent数据",}},methods:{sendClickHandle(){// 参数1:字符串,自定义事件,参数2:传递的数据this.$emit("onEvent",this.message);console.log("mycomponent.vue下 " + this.message);}}
}
</script>

父组件示例:

// App.vue
<template><MyComponent @onEvent="getDataHandle"/><p>{{ recvData }}</p>
</template><script>
import MyComponent from './components/MyComponent.vue';
export default{name:'App',data(){return{recvData:'null',}},components:{MyComponent},methods:{getDataHandle(data){this.recvData = data;console.log("app.vue下 " + this.recvData);}}
}
</script>

注意:<script>内给变量赋值或调用需要使用this.<template>内不需要使用this.

在这里插入图片描述

8 Vue状态管理(Vuex)

上一节的数据传递方式,支持父子组件之间的数据传递,如果多个组件之间不存在直接的关系,则采用vuex库来集中式存储管理应用的所有组件的状态。状态管理更方便的管理组件之间的数据交互,任何组件都可以按照指定的方法读取和改变数据。

包括:State(存储状态)、Getter(获取、计算、过滤)、Mutation(修改)、Action(异步操作)。

8.1 简单数据传递 State

8.1.1安装Vuex

选择文件夹位置,终端输入:

npm install --save vuex

8.1.2 配置Vuex文件

新建文件夹src/store,新建文件index.js,代码如下:

//index.js
import { createStore } from "vuex";// vuex的作用就是帮我们管理组件之间的状态的
export default createStore({// 所有的状态/数据都放在这里state: {counter:2024,name:'vuexSolution',}
})

8.1.3主文件中引入Vuex

进入/src/main.js文件,引入:

//main.js
import './assets/main.css'import { createApp } from 'vue'
import App from './App.vue'import router from './router/index.js'
import store from './store/index.js'const app = createApp(App);
app.use(router);
app.use(store);app.mount('#app');

也可以使用:createApp(App).use(router).use(store).mount('#app')来设置。

8.1.4数据读取

1、方法1:普通读取方式
.vue文件的template中使用$store.state.xxxxx来读取对应名称的数据,script中使用this.$store.state.xxxxx来读取数据代码如下:

//App.vue
<template><p>counter = {{ $store.state.counter }}</p><p>name = {{ $store.state.name }}</p><button @click="vuexParamCheck">alert</button>
</template><script>
export default{methods:{vuexParamCheck(){console.log(this.$store.state.counter);console.log(this.$store.state.name);}}
}
</script>

2、方法2:mapState快捷读取方式
使用vuex内的mapState方式,能够快捷读取数据。放入computed内,...为扩展运算符。

import { mapState } from 'vuex';
//计算属性,专门来读取vuex的数据
coumputed:{...mapState(["counter"])
}

示例代码如下:

// App.vue
<template><p>方法1:counter = {{ $store.state.counter }}</p><p>方法2:name = {{ name }}</p><button @click="vuexParamCheck">console</button>
</template><script>
import { mapState } from "vuex";
export default{methods:{vuexParamCheck(){console.log(this.$store.state.counter);console.log(this.name);}},computed:{...mapState(["name"])}
}
</script>

界面如下:
在这里插入图片描述
点击按钮后可以看到调试界面如下:
在这里插入图片描述

8.2 获取过滤计算 Getter

能够获取state内的数据,并加以过滤/计算后再输出。

8.2.1 配置vuex文件

/src/store/index.js中设置getters,新建函数getCounter(),代码如下:

//index.js
import { createStore } from "vuex";// vuex的作用就是帮我们管理组件之间的状态的
export default createStore({// 所有的状态/数据都放在这里state: {counter:2024,name:'vuexSolution',},getters: {getCounter(state){return state.counter > 2024 ? state.counter:"还没到2024年"},getName(state){return state.name == "vuex" ? state.name: "name error"}}
})

8.2.2 主文件中引入Vuex

同8.1.3,略。

8.2.3 处理过的数据读取

1、方法1:普通读取方法
.vue文件内使用$store.getters.函数名来引用经过过滤/计算的数据。

//App.vue
<template><p>Getter:{{ getName }}</p>
</template>

2、方法2:mapGetters快捷读取方法(类似于8.1.4方法2)

<template><p>Getter:{{ getName }}</p>
</template><script>
import { mapGetters } from 'vuex';
export default{//计算属性,专门来读取vuex的数据coumputed:{...mapGetters(["getName"])}
}
</script>

完整代码:

<template><p>方法1:counter = {{ $store.state.counter }}</p><p>方法2:name = {{ name }}</p><button @click="vuexParamCheck">console</button><p>Getter:{{ $store.getters.getCounter }}</p><p>Getter:{{ getName }}</p>
</template><script>
import { mapState,mapGetters } from "vuex";
export default{methods:{vuexParamCheck(){console.log(this.$store.state.counter);console.log(this.name);}},computed:{...mapState(["name"]),...mapGetters(["getName"])}
}
</script>

8.3 修改参数 Mutation

更改Vuex的store中的状态的唯一方法就是提交mutation。Mutation都有一个字符串的事件类型(type)和一个回调函数(handler),这个回调函数就是我们实际进行状态更改的地方,并且他会接受state作为第一个参数。

8.3.1 配置vuex文件

src/store/index.js中添加mutations方法:

//index.js
import { createStore } from "vuex";// vuex的作用就是帮我们管理组件之间的状态的
export default createStore({// 所有的状态/数据都放在这里state: {counter:2024,name:'vuexSolution',},getters: {getCounter(state){return state.counter > 2024 ? state.counter:"counter数据异常"},getName(state){return state.name == "vuex" ? state.name: "name error"}},mutations:{addCounter(state){state.counter ++;}}
})

8.3.2 主文件中引入Vuex

同8.1.3,略。

8.3.3 调用数据修改函数

/src/App.vue中添加按钮及其事件addClickHandle,在事件中添加mutation的固定调用方式this.$store.commit("addCounter")

代码修改如下:

<template><p>方法1:counter = {{ $store.state.counter }}</p><p>方法2:name = {{ name }}</p><button @click="vuexParamCheck">console</button><p>Getter:{{ $store.getters.getCounter }}</p><p>Getter:{{ getName }}</p><button @click="addClickHandle">counter加1</button>
</template><script>
import { mapState,mapGetters } from "vuex";
export default{methods:{vuexParamCheck(){console.log(this.$store.state.counter);console.log(this.name);},addClickHandle(){this.$store.commit("addCounter");   // 固定调用方式}},computed:{...mapState(["name"]),...mapGetters(["getName"])}
}
</script>

点击按钮可以发现前面两个关联counter的文本数据显示都发生了变化。
在这里插入图片描述

8.3.4 数据输入反馈

当我们在页面输入数据,对store中state的数据产生修改时,需要代码进行如下修改。
以下是src/store/index.js的代码:

//index.js
import { createStore } from "vuex";
export default createStore({mutations:{addCounter(state, num){state.counter = state.counter + num;}}
})

1、方法1:this.$store.commit("xxxxxxx",this.inputNumber)
参考第4节的v-model数据绑定,添加输入文本框以便进行数据传入,以下是src/App.vue的代码:

<template><p>方法1:counter = {{ $store.state.counter }}</p><p>方法2:name = {{ name }}</p><button @click="vuexParamCheck">console</button><p>Getter:{{ $store.getters.getCounter }}</p><p>Getter:{{ getName }}</p><input type="number" v-model="inputNumber"><button @click="addClickHandle">Add</button>
</template><script>
import { mapState,mapGetters } from "vuex";
export default{data(){return{inputNumber:0,}},methods:{vuexParamCheck(){console.log(this.$store.state.counter);console.log(this.name);},addClickHandle(){this.$store.commit("addCounter",this.inputNumber);}},computed:{...mapState(["name"]),...mapGetters(["getName"])}
}
</script>

2、方法2:使用mapMutations,这里要注意的是,...mapMutations(["xxxxxxxx"]),需要放在methods内,而不是computed内!

代码如下:

<template><p>方法1:counter = {{ $store.state.counter }}</p><p>方法2:name = {{ name }}</p><button @click="vuexParamCheck">console</button><p>Getter:{{ $store.getters.getCounter }}</p><p>Getter:{{ getName }}</p><input type="number" v-model="inputNumber"><button @click="addClickHandle">Add</button>
</template><script>
import { mapState,mapGetters,mapMutations } from "vuex";
export default{data(){return{inputNumber:0,}},methods:{...mapMutations(["addCounter"]),		// 注意!!!vuexParamCheck(){console.log(this.$store.state.counter);console.log(this.name);},addClickHandle(){// 调用方式2this.addCounter(this.inputNumber);},},computed:{...mapState(["name"]),...mapGetters(["getName"]),}
}
</script>

输入框内输入数字,点击add就可以看到上方的counter发生了改变
在这里插入图片描述

8.4 异步操作 Action

Action类似于Mutation,不同的是Action提交的是mutation,而不是直接变更状态,Action可以调用mutation中的方法、包含任意异步操作(能够添加网络请求),mutation只能同步操作。

8.4.1 配置vuex文件

src/store/index.js中添加actions方法,actions方法内必须使用异步处理。此处函数为asyncAddCounter,函数内调用mutations内的addCounter函数。asyncAddCounter函数的功能是将网络请求到的值传入addCounter函数内,以修改counter的值。

//index.js
import { createStore } from "vuex";
import axios from "axios";export default createStore({mutations:{addCounter(state, num){state.counter = state.counter + num;}},actions:{asyncAddCounter({commit}){axios.get("http://iwenwiki.com/api/generator/list.php").then(res =>{console.log(res.data);commit("addCounter", res.data[0]);})}}
})

8.4.2 调用函数

调用方法为:this.$store.dispatch("xxxx")。此处点击按钮的响应函数内调用actions。

//App.vue
<template><p>方法1:counter = {{ $store.state.counter }}</p><p>方法2:name = {{ name }}</p><button @click="vuexParamCheck">console</button><p>Getter:{{ $store.getters.getCounter }}</p><p>Getter:{{ getName }}</p><input type="number" v-model="inputNumber"><button @click="addClickHandle">Add</button><button @click="addAsyncClickHandle">异步增加</button>
</template><script>
import { mapState,mapGetters,mapMutations } from "vuex";
export default{data(){return{inputNumber:0,}},methods:{...mapMutations(["addCounter"]),vuexParamCheck(){console.log(this.$store.state.counter);console.log(this.name);},addClickHandle(){console.log("inputNumber: " + this.inputNumber);//this.$store.commit("addCounter",this.inputNumber);// 固定调用方式this.addCounter(this.inputNumber);},addAsyncClickHandle(){this.$store.dispatch("asyncAddCounter");}},computed:{...mapState(["name"]),...mapGetters(["getName"]),}
}
</script>

点击异步增加后,counter会每次增加1001。

在这里插入图片描述

9 生命周期

每个组件在被创建时都要经过一系列的初始化过程。例如,需要设置数据监听、编译模板、将实例挂载到DOM,并在数据变化时更新DOM等。同时在这个过程中也会运行一些叫做生命周期钩子的函数。这给了用户在不同阶段添加自己代码的机会。
自动化调用,无需手动写。

生命周期名称功能
beforeCreate创建前
created创建时
beforeMount渲染前
mounted渲染时网络请求放在此函数内
beforeUpdate更新前
updated更新时
beforeUnmount卸载前卸载消耗性能的处理
uomunted卸载时
<template><p>---------------------------</p><h3>生命周期函数</h3><p>年龄:{{ lifetime }}</p><button @click="lifetime ++">点击改变</button>
</template><script>
export default{name:"MyComponent",data(){return{lifetime:0,}},beforeCreate(){console.log("beforeCreate");},created(){console.log("created");},beforeMount(){console.log("beforeMount")},mounted(){console.log("mounted")// 把网络请求放到这里},beforeUpdate(){console.log("beforeUpdate")},updated(){console.log("updated")},beforeUnmount(){console.log("beforeUnmount")// 卸载之前,把消耗性能的处理都干掉,比如定时器},unmounted(){console.log("unmounted")}
}

可以在调试窗口看到生命周期函数按照顺序执行。
在这里插入图片描述

10 Vue引入第三方

10.1 轮播图——Swpier

Swpier是触摸滑动插件,纯js打造的,面向手机、平板电脑等移动终端。
官方文档:

https://swiperjs.com/vue

1、首先下载Swiper,命令行内输入:

npm install --save swiper

2、添加Swiper、Pagination(页码)和Autoplay(自动轮播),实现多张图片自动轮播。

<template><div><swiper :modules="modules" :pagination="{clickable:true}" :autoplay="{autoplay: true, delay: 3000}"><swiper-slide><img src="../assets/1.jpeg" alt=""></swiper-slide><swiper-slide><img src="../assets/3.jpeg" alt=""></swiper-slide><swiper-slide><img src="../assets/6.jpeg" alt=""></swiper-slide></swiper></div>
</template><script>import {Pagination, Autoplay} from 'swiper/modules';import {Swiper,SwiperSlide} from 'swiper/vue';import 'swiper/css';import 'swiper/css/pagination';import 'swiper/css/autoplay';export default{name:"helloworld",components:{Swiper,SwiperSlide,},data(){return{modules:[Pagination,Autoplay]}},}
</script><style scoped>
img{width:100%
}
</style>

三张图片能够以3秒间隔循环播放。
在这里插入图片描述

10.2 Axios网络请求库

Axios是基于promise的网络请求库。

1、安装:

npm intall --save axios

2、引入:

import axios from ‘axios’

<template><div><p>res_data:{{ res_data }}</p><p>error_data:{{ error_data }}</p></div>
</template><script>
import axios from 'axios';export default{name:'TheWelcome',data(){return{res_data:'',error_data:'',}},mounted(){console.log("mounted");// 网络请求axios({method:'get',url:'http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php',// 使用http可以连接,使用https无法连接}).then(res =>{console.log(res.data);this.res_data = res.data;}).catch(error =>{console.log(error.data);this.error_data = error.data;})}
}
</script>

连接HTTP正常,连接HTTPS可能会出现跨域问题。

在这里插入图片描述

10.3 Axios网络请求封装

1、在src下新建api文件夹,新建index.jspath.js

// index.js
import axios from "../utils/request";
import path from "./path";const api = {// 成品详情地址getChenpin(){return axios.get(path.baseUrl + path.chengpin)}
}export default api;

path.js文件下输入地址。

//path.js
const base = {baseUrl:"http://iwenwiki.com/",chengpin:"api/blueberrypai/getChengpinDetails.php",
}export default base;

2、在src文件下新建utils文件夹,新建request.js,用于网络请求打包。

// request.js
import axios from "axios";
import querystring from 'querystring';const errorHandle = (status, info) => {switch(status){case 400:console.log("语义有误");break;case 401:console.log("服务器认证失败");break;case 403:console.log("服务器拒绝访问");break;case 404:console.log("地址错误");break;case 500:console.log("服务器遇到意外");break;case 502:console.log("服务器无响应");break;default:console.log(info);break;}
}const instance = axios.create({// 网络请求的公共配置timeout:5000,
})// 拦截器最常用的函数如下// 发送数据之前
instance.interceptors.request.use(config =>{      // 包含网络请求的所有信息if(config.method === "post"){config.data = querystring.stringify(config.data);   // 转换}return config;},error =>{return Promise.reject(error);}
)// 获取数据之前
instance.interceptors.response.use(response =>{return response.status === 200 ? Promise.resolve(response): Promise.reject(response);},error =>{const {response} = error;       // 错误的处理才是我们最需要关注的errorHandle(response.status, response.info);}
)export default instance;

3、主文件内引用刚才的封装。

<template><div></div>
</template><script>import api from '../api/index.js'export default{name:"helloworld",data(){return{}},methods:{},mounted(){		// 渲染完成后,调用网络请求api.getChenpin().then(res =>{console.log(res.data);}).catch(error => {console.log(error.data);});}}
</script>

可以再控制台内看到如下信息:

在这里插入图片描述

10.4 网络请求的跨域问题

JS采用的是同源策略。浏览器只允许JS代码请求和当前所在服务器域名、端口、协议相同的数据接口上的数据,这就是同源策略。当协议、域名、端口任意一个不相同时,都会产生跨域问题。

Access to XMLHTTPRequest at ‘https://www.baidu.com
/’
from origin ‘http://localhost:5173’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource

两种主流解决方案:
1、后台解决:cros
2、前台解决:proxy(代理)
这里主要讲解前台处理方法:进入vite.config.js文件,添加server设置(新版本的Vue3必须是server,devServer无法连接)。

import { fileURLToPath, URL } from 'node:url'import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(),],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}},server:{//port:5173,//open:true,//cors:true,proxy:{'/api':{target:'http://iwenwiki.com',changeOrigin:true}}}
})

然后修改HelloWorld.vue中的网址。

// HelloWorld.vue
<template><div><h3>跨域解决方案proxy</h3></div>
</template><script>
import axios from 'axios'export default{name:'HelloWorld',mounted(){axios.get('/api/FingerUnion/list.php')	// 前面相同的域名不用谢了,只需要写后面的/.......then(res =>{console.log(res.data);});}
}
</script>

vite.config.js配置完成后需要重启服务器。
可以看到调试界面显示了返回的数据。

在这里插入图片描述

经过试验,这似乎也不能完全解决所有跨域问题。

11 路由Router

11.1 Router路由配置

通过vue-router路由管理页面之间的跳转。Vue Router是Vue.js的官方路由。
router可以管理多个页面,并方便进行多个页面的跳转。

11.1.1 安装路由

npm install --save vue-router

11.1.2 配置独立的路由文件

在src文件夹下,新建router文件夹,新建index.js文件,配置如下:

  • 导入路由库
  • 导入页面,这里导入两个HomeView.vue和AboutView .vue
  • 配置routes,设置多个页面的路径path与组成component。

component:() => import("../views/xxxxx.vue")为异步执行,如果不显示相应页面,则不执行相应代码(不创建渲染页面,节约资源)。
component: xxxxxx为同步执行。一般首页直接引入component,其他页使用异步执行。

  • 使用createRouter()函数管理。
  • 导出router,以便其他文件使用。
import { createRouter, createWebHashHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
import AboutView from "../views/AboutView.vue";const routes = [{path:"/home",component:HomeView,},{path:"/about",component:AboutView,}
]// 配置信息中需要页面的相关配置
const router = createRouter({history: createWebHashHistory(),routes,
})export default router;

注意:

  • createWebHashHistory() 网址内带/#/,不需要后台配合做重定向。原理:a标签锚点链接。
  • createWebHistory() 网址更简单,不带/#/,需要后台配合做重定向,否则会出现404问题。原理:H5 pushState()。

11.1.3 创建网页(这一步可以放在10.1.2之前)

在src文件夹下创建views文件夹,在文件夹内创建AboutView.vue和HomeView.vue两个文件。
代码如下:

// AboutView.vue
<template><h3>关于页面</h3><div>你好世界!</div>
</template>
// HomeView.vue
<template><h3>首页</h3><div>Hello, World!</div>
</template>

11.1.4 引入路由到项目内

修改main.js文件

import './assets/main.css'import { createApp } from 'vue'
import App from './App.vue'import router from './router/index.js'createApp(App).use(router).mount('#app')

11.1.5 指定路由显示入口

在App.vue的template内添加<router-view></router-view>或者<router-view />

11.1.6 指定路由跳转

使用<router-link to="/home"></router-link>来设置路由跳转链接。

代码如下:

// App.vue
<script setup>
import HelloWorld from './components/HelloWorld.vue';
</script><template><HelloWorld /><router-link to="/home">首页</router-link> |<router-link to="/about">关于页面</router-link><router-view></router-view>
</template>

11.2 路由传递参数

通过路由链接点击时,能传递一定的信息到新的页面。

11.2.1 创建下级页面

在NewsView.vue下创建多个新闻类别,在views文件夹下新建NewsDetails.vue
代码如下:

//NewsDetails.vue
<template><h3>新闻详情</h3>
</template>

11.2.2 添加路由信息和指定参数key

进入src/router/index.js,添加routes,并在path最后添加/:param1,表示参数的名称为param1。

//index.js
{path:"/news/details/:param1",name:"details",component:() => import("../views/NewsDetails.vue"),
}

11.2.3 添加路由链接和需要携带的参数

修改src/views/NewsView.vue,添加无序列表,列表项内添加路由链接,并在链接后添加/ABCD,ABCD为携带的参数。

//NewsView.vue
<template><h3>新闻</h3><ul><li><router-link to="/news/details/国内新闻">国内新闻</router-link></li><li><router-link to="/news/details/国际新闻">国际新闻</router-link></li><li><router-link to="/news/details/经济新闻">经济新闻</router-link></li><li><router-link to="/news/details/军事新闻">军事新闻</router-link></li></ul>
</template><script>
export default{mounted(){console.log("NewsView.vue mounted!")},unmounted() {console.log("NewsView.vue unmounted!")},
}
</script>

11.2.4 跳转页读取路由携带的参数

使用{{ $route.params.name }}获取参数。
$route.params.是固定的,后面的name要根据src/router/index.js内的path: "/news/details/:param1"来,这里为param1
下方代码在进入页面渲染完成后,会输出param1的信息,点击按钮会将param1信息显示在Info1后面。

// NewsDetails.vue
<template><h3>新闻详情</h3><p>{{ $route.params.param1 }}</p><button @click="readParam">读取</button><p>Info1: {{ trans1 }}</p>
</template><script>
export default{data(){trans1: "",},methods: {readParam(){this.trans1 = this.$route.params.param1;},},mounted(){console.log("NewsDetails.vue mounted!");console.log(this.$route.params.param1);},unmounted(){console.log("NewsDetails.vue unmounted!");}
}
<script>

注意:如果需要传递更多的参数,

  • 则在src/router/index.js中使用/news/details/:param1/:param2
  • src/views/NewsView.vue中使用<router-link to="/news/details/军事新闻/ABCDEFG">
  • src/views/NewsDetails.vuetemplate中读取参数使用{{ $route.params.param1 }}{{ $route.params.param1 }}script中读取参数使用this.route.params.param1this.route.params.param2

11.3 嵌套路由配置

主导航目录下的项目有多个子导航目录。
在About下设置子导航。

11.3.1 新建子页面

新建文件夹src/views/AboutSubview,新建文件AboutInfo.vueAboutUs.vue

//AboutUs.vue
<template><div>我们是来自M78星云的咸蛋超人。</div>
</template>
//AboutInfo.vue
<template><div>如果你想要打怪兽,请随时联系我们,我们电话是:114514</div>
</template>

11.3.2 设置子网页路由

/src/router/index.js在about路径下设置children路由,代码如下:

// index.js
const routes = [{path:"/about",name:"about",component:() => import("../views/AboutView.vue"),children:[{//二级导航的路径不要加斜杠path:"us",component:() => import("../views/AboutSubview/AboutUs.vue"),},{path:"info",component:() => import("../views/AboutSubview/AboutInfo.vue"),},]},
]

11.3.3 对应页面下设置路由

src/views/AboutView.vue下添加路由链接和显示入口。

//AboutView.vue
<template><h3>关于</h3><router-link to="/about/us">我们</router-link> |<router-link to="/about/info">信息</router-link><router-view></router-view>
</template>

11.3.4 设置默认界面

点击主导航栏后,进入子页面,需要设置一个子页面的子导航栏的默认页面。这里需要用到重定向redirect
/src/router/index.js中about路径下添加redirect:"/about/xxx",代码如下:

// index.js
const routes = [{path:"/about",name:"about",redirect:"/about/us",component:() => import("../views/AboutView.vue"),children:[{//二级导航的路径不要加斜杠path:"us",component:() => import("../views/AboutSubview/AboutUs.vue"),},{path:"info",component:() => import("../views/AboutSubview/AboutInfo.vue"),},]},
]

如下图所示,一点击“关于页面”,就默认显示“我们”。
在这里插入图片描述

12 局域网内打开网页

首先找到文件夹下的package.json文件,将"dev":"vite"修改为"dev": "vite --host 0.0.0.0"
在这里插入图片描述

重新启动服务器,然后就可以看到调试窗口内出现了新的网址,在局域网内输入该网址就可以打开该网页。

在这里插入图片描述
手机上显示网页。

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python使用PyMySql增删改查Mysql数据库
  • shell 切片参数解释
  • BUUCTF Reverse/[2019红帽杯]Snake
  • 手拉手后端Springboot整合JWT
  • 开源可观测性平台Signoz(四)【链路监控及数据库中间件监控篇】
  • 2024年原创深度学习算法项目分享
  • HTML进阶
  • WPF 新手指引弹窗
  • Spring通信传参的方法
  • AI人工智能大模型讲师叶梓《基于人工智能的内容生成(AIGC)理论与实践》培训提纲
  • OpenCV-Python(22):2D直方图
  • TensorFlow Hub模型
  • 拓展操作(三) jenkins迁移到另一个机器
  • 关键字:try-catch关键字
  • Ubuntu安装WordPress并使用Nginx作为Web服务器
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • canvas绘制圆角头像
  • crontab执行失败的多种原因
  • Git同步原始仓库到Fork仓库中
  • JavaScript DOM 10 - 滚动
  • JavaScript类型识别
  • mysql 数据库四种事务隔离级别
  • mysql_config not found
  • Python_OOP
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 关于extract.autodesk.io的一些说明
  • 聚簇索引和非聚簇索引
  • 免费小说阅读小程序
  • 扑朔迷离的属性和特性【彻底弄清】
  • 前端临床手札——文件上传
  • 为什么要用IPython/Jupyter?
  • 携程小程序初体验
  • 一个SAP顾问在美国的这些年
  • 怎么把视频里的音乐提取出来
  • 字符串匹配基础上
  • 《天龙八部3D》Unity技术方案揭秘
  • raise 与 raise ... from 的区别
  • 容器镜像
  • 数据库巡检项
  • ​MySQL主从复制一致性检测
  • ​香农与信息论三大定律
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (Java入门)学生管理系统
  • (pojstep1.3.1)1017(构造法模拟)
  • (备忘)Java Map 遍历
  • (苍穹外卖)day03菜品管理
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)