我是靠谱客的博主 醉熏天空,最近开发中收集的这篇文章主要介绍$attrs中的对象没有变化,但触发了watch监听?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

$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 收集到 depsubs 里面,从而在设置时进行派发更新notify(),通知视图渲染。

$attrs的依赖收集发生在v-bind中, 通过vue-template-compiler 编译源代码即可发现。
所以当 input 中 v-model 的值更新时,触发 set 通知更新,而在更新组件时调用的 updateChildComponent 方法中会对 $attrs 进行赋值。

所以会触发 $attrsset ,导致它所在的 Watcher 进行更新,也就会导致子组件更新了。而如果没有绑定 v-bind="$attrs" ,则虽然也会到这一步,但是没有依赖收集的过程,就无法去更新子组件了。

最后

以上就是醉熏天空为你收集整理的$attrs中的对象没有变化,但触发了watch监听?的全部内容,希望文章能够帮你解决$attrs中的对象没有变化,但触发了watch监听?所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部