我们之前学习过侦听器watch,它用来侦听数据变化,让我们可以在数据变化以后,做一些操作,比如向后台请求数据等。这节课我们继续学习关于watch的更多内容。
1.deep属性
如果使用watch监听一个对象或者数组,当对象和数组里面的数据发生变化时,是不会触发监听器的,
我们来看下面这个例子
<template>
<div>
<ul>
<li v-for="item in list" :key="item">
{{ item }}
</li>
</ul>
<div>{{ person.name }}的年龄是{{ person.age }}岁</div>
</div>
</template>
<script>
// watch进阶
export default {
name: 'App',
data() {
return {
list: ['苏格拉底', '柏拉图', '亚里士多德'],
person: {
name: '苏格拉底',
age: 18,
},
}
},
watch: {
list(newVal, oldVal) {
console.log('list数组改变了')
console.log('改变以后的值' + newVal)
console.log('改变以前的值' + oldVal)
},
person(newVal, oldVal) {
console.log('person的数据变化了')
console.log('改变以后的值' + newVal)
console.log('改变以前的值' + oldVal)
},
},
mounted() {
// 在组件挂载以后,改变对象和数组里面的数据
this.list.push('亚历山大')
this.person.age = 19
},
}
</script>
<style></style>
运行以后发现,控制台什么都没有打印,说明侦听器确实也没有触发,
但是实际开发中难免有这种需求,需要数组和对象变化时处理一些逻辑
这是就需要deep出场了
deep我们知道是深的意思,这里就是我们要深度侦听这个对象,它里面发生了变化也要触发侦听
现在就需要改变一下watch的写法了,
watch: {
list: {
deep: true,
handler: function(newVal, oldVal) {
console.log('list数组改变了')
console.log('改变以后的值' + newVal)
console.log('改变以前的值' + oldVal)
},
},
person: {
deep: true,
handler: function(newVal, oldVal) {
console.log('person的数据变化了')
console.log('改变以后的年龄' + newVal.age)
console.log('改变以前的年龄' + oldVal.age)
},
},
},
需要被监听的数据作为一个键,它的值是一个对象,对象里添加了一个deep属性,值是true,说明要对这个数据进行深度侦听,handler就是我们之前写的数据发生变化以后的回调函数
这里需要注意,handler这个函数必须使用function,而不能使用箭头函数,因为vue要指定这个函数里面的this指针指向我们当前这个vue组件
现在运行代码,发现控制台输出了
说明侦听器确实触发了,但是有个问题,newVal和值和oldVal的值是一样的,因为对象和数组的引用地址并没有变,所以它们是一样的,这里需要注意一下。
先来小总结一下,有3点需要注意
1)侦听器从函数方式改成了对象方式
2)handler的回调函数必须使用function的方式定义
3)对象和数组改变时,新值和旧值是相同的
如果确实需要得到对象里面数据变化前后的值,可以用这种方式
watch: {
'person.age': {
handler: function(newVal, oldVal) {
console.log('person的数据变化了')
console.log('改变以后的年龄' + newVal)
console.log('改变以前的年龄' + oldVal)
},
},
},
这里侦听的键变成了一个字符串,表示要专门侦听person的age属性,这时不用deep也可以侦听到变化了,同时可以获取新值和旧值
2.immediate
immediate本来就是‘立即’的意思,我们可以给要watch对象增加immediate:true,表示在页面初始化时,就调用侦听的回调函数
'person.age': {
handler: function(newVal, oldVal) {
console.log('person的数据变化了')
console.log('改变以后的年龄' + newVal)
console.log('改变以前的年龄' + oldVal)
},
immediate: true,
同时新增了生命周期函数的打印,来表明侦听执行的时机
beforeCreate() {
console.log('创建之前')
},
created() {
console.log('创建完成')
},
结果是
在beforeCreate之后,created之前执行了回调函数,
这里我们发现改变之前的值是undefined,因为这个值之前还没有定义
这就是immediate的用法
3.flush
flush选项表示回调函数调用的时机,有三个值可以选择
pre:默认值,表示在dom更新前调用,比如这是你需要再改变其他数据,就使用pre,这些数据改变完一起更新dom,提高性能
post:表示dom更新完成后调用,比如你要获取dom或者子组件,跟我们之前使用nextTick的意思一样
sync:同步调用,官网表示不要用这个
4.$watch用法
除了我们定义watch对象的方式添加侦听,也可以是用this.$watch方法
created() {
console.log('创建完成')
this.$watch(
'person.age',
(newVal, oldVal) => {
console.log('person的数据变化了')
console.log('改变以后的年龄' + newVal)
console.log('改变以前的年龄' + oldVal)
},
{
immediate: true,
}
)
},
这时候就可以用箭头函数了
$watch的语法就是这样了,接受三个参数
this.$watch(
要侦听的数据,
回调函数,
选项
)
},
同时$watch方法返回一个方法,用于去掉监听
created() {
console.log('创建完成')
const unwatch = this.$watch('person.age', (newVal, oldVal) => {
console.log('person的数据变化了')
console.log('改变以后的年龄' + newVal)
console.log('改变以前的年龄' + oldVal)
})
unwatch()
},
关于watch的所有用法基本都介绍完了,大家可以动手写一写,体会一下。