关于deep 和 immediate 的基础概念,参见官方文档API — Vue.js
这里说一下deep 和 immediate 在实战中的一个应用场景:
背景
页面有一个从父组件接受到的params属性值,代表向后端发送请求的参数,我需要监听params属性值,一旦父组件传进来的params发生变化就重新向后端发送请求更新数据。
props: {
params: {
type: Object,
default: () => ({
city: "",
time: "",
username: "",
status: {
a: []
b: {}
}
......
})
}
}
watch: {
params:{
immediate:true,
deep:true,
handler(nv, ov) {
if (nv.startTime && nv.endTime) {
this.queryOrderList()
}
}
}
}
this.queryOrderList就是发送请求的函数。
immediate
当页面初始化,params被创建时,此时是不会触发handler的,背后的逻辑就是:刚刚才创建变量params,它还是一张白纸呢,在这张白纸上写写画画才算是"改变",才需要handler。
immediate的作用就是打破这个逻辑,即:当页面初始化,params被创建时,也会触发handler。
那么我们为什么需要immediate呢?
params是父组件传递进来的用户输入的参数,比如说我需要根据一定的筛选条件查询一个信息,地点在"杭州"
,时间是"2021.2.5"
,用户名是"admin"
,这些标红的都是params对象的属性,是要封装成JSON发送给后端的。当页面初始化的时候,params里的属性都是空值,此时我想把空值传给后端(表示无筛选条件)获取所有的数据,此时就需要用到immediate了。
deep
params属性的类型是什么?Object
,属于javascript里的引用类型,params这个字符串本身指向的是堆空间的一个地址,在这块地址上存放params对象的具体内容。默认情况下,watch params
这个变量,监听的是栈空间中的params
本身,也就是它指向的地址是否变化。如果我把params赋值成null,那么此时watch的 handler
就会响应。
但是堆空间中params
指向的对象,它有自己的属性,比如city
,time
,username
,甚至于status
还会嵌套数组对象a
和普通对象b
,这些属性的改变会影响params
本身指向的地址吗?答案是不会的(如果params的属性占用内存过大可能会引起地址重新分配,但这不在讨论范围内)。
既然如此,只监听栈空间中的params
本身,本质上就是在监听它指向的堆空间的地址,是无法监听到子元素的变化的,deep属性就解决了这个问题,采用递归的方式遍历监听params
的每一个子元素。
这样,每当用户输入的city
,time
,username
等等属性改变时,就会触发handler
,发送this.queryOrderList
请求。