概述
$attrs 奇怪现象:绑定的数据没有变化,但watch触发了
假设$attrs中有个变量info
1、当info不管是基本数据类型还是引用数据类型时, 都存在以下问题: 不管这个对象改没改变,handler都执行了
// 父组件调用card
<card :info="info"></card>
data中的info: {a:1} // 为1 同样有这个问题
// 在子组件card组件中监听
watch: {
'$attrs.info': {
handler(newV, oldV){
console.log(newV == oldV) // false , {a:1}明明没有改变,但watch认为它是个新的
},
deep: true,
immediate: true,
}
}
导致这种情况的原因是:
是父组件的非info
数据的变化导致了父组件及其子组件的更新,$attrs
是响应式数据,子组件更新导致
$attrs
被重新赋值了,即使监听的info
没有变化。因为$attrs
变化了,所以watch执行了。
解决方案
1、可以通过判断info的值是否一样
watch: {
'$attrs.info': {
handler(newV, oldV){
if (!_.isEqual(newVal, value)) {
console.log('值变化才触发')
}
},
deep: true,
immediate: true,
}
}
2、通过props 接收info,并对info进行监听,就不存在这个问题
info:{
handler(newV,old) {
console.log('info改变了,触发')
},
deep: true,
immediate: true,
}
1、 基本数据类型
只有值改变时才触发watch
2、引用数据类型
同一个引用,内容改变,触发;
引用地址变化,触发;
watch内部的判断是:
不同的对象都不相等, 即使内部数据一样,对象(引用数据类型,如数组)只有引用地址一样才是相同的
比如:对象浅拷贝,内部数据是同一个引用
var obj1 = {
'a':{name: 123},
'b':{name: 45}
}
var obj2 = {...obj1}
console.log(obj1.a === obj2.a) // true
$attrs 数据没有变化,却让子组件更新的原因
参考来源: https://www.jb51.net/article/194252.htm
大概总结一下:
在子组件有v-bind="$attrs"
,就会在 initRender 方法中,将 $attrs
属性绑定到了 this 上,并且设置成响应式对象。Vue
通过 Object.defineProperty
方法进行依赖收集, 我们在访问 $attrs
时,它( dep
)会将 $attrs 所在的 Watcher
收集到 dep
的 subs
里面,从而在设置时进行派发更新notify()
,通知视图渲染。
$attrs
的依赖收集发生在v-bind中, 通过vue-template-compiler
编译源代码即可发现。
所以当 input 中 v-model
的值更新时,触发 set 通知更新,而在更新组件时调用的 updateChildComponent
方法中会对 $attrs
进行赋值。
所以会触发 $attrs
的 set
,导致它所在的 Watcher
进行更新,也就会导致子组件更新
了。而如果没有绑定 v-bind="$attrs"
,则虽然也会到这一步,但是没有依赖收集的过程,就无法去更新子组件了。
最后
以上就是醉熏天空为你收集整理的$attrs中的对象没有变化,但触发了watch监听?的全部内容,希望文章能够帮你解决$attrs中的对象没有变化,但触发了watch监听?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复