使用过watch的,应该起码经历过一次失效。
比如,我们监听对象的时候,在没有踩坑之前,很容易这样写:
但是,"htmlcode">
let obj = { a: 1 }; let obj1 = obj; let obj2 = { ...obj }; obj1.a = 2; obj2.a = 3; // 这里肯定是true,因为obj和obj1都是同一个指针,不明白的搜下引用类型 console.log(obj1 === obj); // 这里肯定是false,因为指针不同 console.log(obj2 === obj);
怎么解决呢?也简单!
设置deep:true,这样obj中的属性发生变化(可被监测到的),便会执行 handler 函数;。
!!!注意,因为是引用类型,所以newValue 和oldValue始终相等,千万不要犯傻的写相等就return,那就永远也不往下走了。。。。
监测数组
引用类型,除了对象,很容易想到数组,那数组是不是也需要这样写呢。
话分两头:
- 数组项是对象类型,就需要deep
- 数组项是值类型,就不需要deep
因为vue2里,数组被特殊处理了,跟 obj 不等同,所以需要分情况。
也就是数组项是值类型的话,直接这么写就行:
对象类型的话,上面是不行的,先举个错误 "text-align: center">
不打印的原理,依然是数组项是对象类型,想watch对象类型,必须加deep
正确做法 "htmlcode">
watch:{ arr: { handler(newValue) { // 这里就可以打印了 console.log(newValue); }, deep: true }, }
总结
watch失效的场景:
- 对象类型
- 数组项为对象类型的数组
解决方案:加deep:true。
watch的其他属性
官网文档
- 一开始就需要执行watch的话,可 immediate属性
- handle可以是一个数组
- 取消watch的话,this.$unwatch
- watch对象的某个属性的话,'obj.key'(){}
- 如果想同时检测两个属性,懒得一个个写的话,有个偷懒的法子用computed做中间层。
computed:{ fullName(){return this.firstName + this.lastName} }, watch:{ fullName(){...} }
引用
watch的用法