1. watch侦听器
wach侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。例如,监视用户名的变化并发起请求,判断用户名是否可用。
1.1 基本语法
开发者需要在watch节点下,定义自己的侦听器:
export default{
data(){
return { username:'' }
},
watch:{
username(newVal,oldVal){
console.log(newVal,oldVal)
},
},
}
1.2 检测用户名是否可用
import axios from 'axios'
export default{
data(){
return {username:''}
},
watch:{
async username(newVal,oldVal){
const {data:res} =await axios.get('https://www.abv,com/api/${newVal}')
console.log(res)
}
}
}
1.3 immediate选项
默认情况下,组件在初次加载完毕后不会调用watch侦听器,如果想让watch侦听器立即被调用,则需要使用 immediate
选项:
watch: {
// 1.监听username的变化
username: {
// 2.handler属性是固定写法,当username变化时,调用handler
async handler(newVal, oldVal) {
const { data: res } = await axios.get('https://www.abv,com/api/${newVal}');
console.log(res);
},
//3.表示组件加载完毕后立即调用一次当前的watch侦听器
immediate: true,
},
},
1.4 deep选项
当watch侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到,此时需要用到deep选项:
data() {
return {
info: { username: 'admin' }, //info中包含username属性
};
},
watch: {
// 直接监听info对象的变化
info: {
async handler(newVal, oldVal) {
const { data: res } = await axios.get('https://www.abv,com/api/${newVal.username}');
console.log(res);
},
deep: true, //需要使用deep选项,否则username的值无法被监听到
},
},
1.5 监听对象单个属性的变化
如果只想监听对象中单个属性的变化,则可以按照如下的方式定义watch侦听器:
data() {
return {
info: { username: 'admin', password: '' }, //info中包含username属性
};
},
watch: {
'info.username': {
//只想监听info.username属性值的变化
async handler(newVal, oldVal) {
const { data: res } = await axios.get('https://www.abv,com/api/${newVal}');
console.log(res);
},
},
},
1.6 计算属性 VS 侦听器
计算属性和侦听器侧重的应用场景不同:
- 计算属性侧重于监听多个值的变化,最终计算并返回一个新值
- 侦听器侧重于监听单个数据的变化,最终执行特定的业务处理,不需要有任何返回值
2. 组件的生命周期
组件的生命周期指的是:组件从创建->运行(渲染)->销毁的整个过程,强调的是一个时间段。
开始 —> import导入组件 —> components注册组件 —> 以标签形式使用组件 —> 在内存中创建组件的实例对象 —> 把创建的组件实例渲染到页面上 —> 组件切换时销毁需要被隐藏的组件 —> 结束
2.1 监听组件的不同时刻
vue框架为组件内置了不同时刻的生命周期函数,生命周期函数回伴随着组件的运行而自动调用。
- 当组件在内存中被
创建
完毕之后,会自动调用created
函数。 - 当组件被成功的
渲染
到页面上之后,会自动调用mounted
函数。 - 当组件被
销毁
完毕之后,会自动调用unmounted
函数
2.2 监听组件的更新
当组件的data数据更新之后,vue会自动重新渲染组件的DOM结构,从而保证View视图展示的数据和Model数据源保持一致。
当组件被重新渲染完毕之后,会自动调用updated生命周期函数。
2.3完整的生命周期函数
3. 组件之间的数据共享
3.1组件之间的关系
在项目开发中,组件之间的关系分为如下3种:
- 父子关系
- 兄弟关系
- 后代关系
3.2 父子组件之间的数据共享
父子组件之间的数据共享又分为:
- 父 -> 子共享数据
- 子 -> 父共享数据
- 父 <-> 子双向数据同步
3.3.1 父组件向子组件共享数据
父组件通过v-bind属性绑定向子组件共享数据:
<MyTest :msg="message" :user="userinfo"></MyTest>
data(){
return{
message:'hello vue',
userinfo:{name:'zs'age:20},
}
}
同时,子组件需要使用props接收数据:
//子组件
<template>
<h3>测试父子传值 </h3>
<p> {{msg}} </p>
<p> {{user}} </p>
</template>
<script>
export default{
props:['msg','user'],
}
</script>
3.3.2 子组件向父组件共享数据
子组件通过自定义事件的方式向父组件共享数据:
//子组件
export default{
emits:['nchange'],//1.声明自定义事件
data(){return {n:0}},
methods:{
addN(){
this.n++
//2.数据变化时,触发自定义的事件
this.$emit('nchange',this.n)
}
}
}
//父组件
//1.监听子组件的自定义事件 nchange
<MyTest @nchange="getn"></MyTest>
export default{
data(){return{nFormSon:0}},
methods:{
getn(n){//1.通过形参,接收子组件传递过来的数据
this.nFromSon=n
}
}
}
3.3.3 父子组件之间数据的双向同步
父组件在使用子组件期间,可以使用v-model指令维护组件内外数据的双向同步:
3.3 兄弟组件之间的数据共享
兄弟组件之间实现数据共享的方案是EventBus。可以借助于第三方的包mitt来创建eventBus对象,从而实现兄弟组件之间的数据共享。
创建EventBus
const bus = mitt()
export defult bus
在数据的接收方和发送方共享EventBus对象
导入并得到EventBus实例对象
import bus from './eventBus.js'
调用EventBus的on()方法,声明自定义事件,通过事件回调接收数据
bus.on('自定义事件',(data)=>{})
3.4.1 具体步骤
1. 安装mitt依赖包
在项目中运行如下的命令,安装mitt依赖包
npm install mitt@2.1.0
2. 创建公共的EventBus模块
在项目中创建公共的eventBus模块:
//eventBus.js
//导入mitt包
import mitt from 'mitt'
//创建EventBus的实例对象
const bus = mitt()
//将EventBus的实例对象共享出去
export default bus
3. 在数据接收方自定义事件
在数据接收方,调用 bus.on('事件名称',事件处理函数)
方法注册一个自定义事件:
//导入eventBus.js模块,得到共享的bus对象
import bus from './eventBus.js'
export default{
data(){return {count:0}},
created(){
//调用bus.on()方法注册一个自定义事件,通过处理函数的形参接收数据
bus.on('countChange',(count)=>{
this.count = count
}
}
}
4. 在数据发送方触发事件
在数据发送方,调用bus.emit('事件名称',要发送的数据)方法触发自定义事件:
//导入eventBus.js模块,得到共享的bus对象
import bus from './eventBus.js'
export default{
data(){return{count:0}},
methods:{
addCount(){
this.count++
bus.emit('countChange',this.count)//调用bus.emit()方法触发自定义事件,并发送数据
}
}
}
3.4 后代关系组件之间的数据共享
后代关系组件之间共享数据,指的是父节点的组件向其子孙组件共享数据。
此时组件之间的嵌套关系比较复杂,可以使用provide和inject实现后代关系组件之间的数据共享。
3.4.1 父节点通过provide共享数据
父节点的组件可以通过 provide 方法,对其子孙组件共享数据:
export default{
data(){
return{
color:'red'//定义父组件要向子孙组件共享的数据
}
},
provide(){//provide函数return的对象中,包含了要向子孙组件共享的数据
return{
color:this.color,
}
},
}
3.4.2 子孙节点通过inject接收数据
子孙节点可以使用inject数组,接收父级节点向下共享的数据:
export default{
inject:['color'],
}
3.4.3 父节点对外共享响应式的数据
父节点使用provide向下共享数据时,可以结合computed函数向下共享响应式的数据。
import {computed} from 'vue' //从vue中按需导入computed函数
export default{
data(){
return{color:'red'}
},
provide(){
return{
color:computed(()=>this.color),
}
},
}
3.4.4 子孙节点使用响应式的数据
如果父级节点共享的是响应式的数据,则子孙节点必须以.value的形式使用。
<template>
<h5>子孙组件--- {{color.value}} </h5>
</template>
<script>
export default{
//接收响应式color数据,并在页面上使用
inject:['color'],
}
</script>
3.5 vuex
vuex 是终极的组件之间的数据共享方案,在企业级的vue项目开发中,vuex可以让组件之间的数据共享变得更高效、清晰、且易于维护。
Vue3.x中全局配置axios
在实际项目开发中,几乎每个组件都会用到axios发起数据请求,此时会遇到如下两个问题:
- 每个组件中都需要导入axios(代码臃肿)
- 每次发请求都需要填写完整的请求路径(不利于后期的维护)
配置方式
在main.js入口文件中,通过 app.config.globalProperties
全局挂载axios
//为axios配置请求的根路径
axios.defaults.baseURL='http://api.com'
//将axios挂载为app的全局自定义属性之后
//每个组件可以通过this直接访问到全局挂载的自定义属性
app.config.globalProperties.$http = axios
在组件中发起axios请求:
this.$http.get('/users')