iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Vue3 Watch踩坑实战之watch监听无效
  • 102
分享到

Vue3 Watch踩坑实战之watch监听无效

vue watch监听vue watch监听vue watch监听函数 2023-05-19 08:05:18 102人浏览 泡泡鱼
摘要

目录ref 与 Reactivewatch总结ref 与 reactive ref函数和reactive函数都是用来定义响应式数据 但是reactive更适合定义引用类型、ref适合

ref 与 reactive

ref函数和reactive函数都是用来定义响应式数据

但是reactive更适合定义引用类型、ref适合定义基本数据类型(可接收基本数据类型和对象)

reactive

1、 深层次响应式,本质是将传入的数据包装成一个Proxy对象

2、 参数必须是对象或者数组,如果要让对象的某个元素实现响应式时,需要使用toRefs,这样每个都需要采用value方式访问

ref

1、函数参数可以是基本数据类型,也可以接受对象类型

2、如果参数是对象类型时,其实底层的本质还是reactive

3、ref响应式原理是依赖于Object.defineProperty()的get()和set()的

watch

在自身组件监听 reactive 对象

let a = reactive({test: 123, bg: 456, hh: {hhh: 78}})
// 定时器 1
setTimeout(() => {
  a.test = 456
}, 2000)
// 定时器 2
setTimeout(() => {
  a.hh.hhh = 56 
}, 4000)
// 定时器 3
setTimeout(() => {
  a = {}  
}, 6000)
// 
watch(a, () => {
  // 定时器1, 2 可以触发监听, 不需要deep也可以
  // 定时器3 不能触发监听, 因为对象的地址已经发生改变了
  console.log("change")
})
// 函数返回方式 采用deep可以监听, 不加deep不能监听 
watch(
  () => a,
  () => {
    console.log(" func change")
  },
  {
     deep: true
  }
)

为什么不加 deep不能监听呢,直接从源码

  function watch(source, cb, options) {
    if (!isFunction(cb)) {
      warn2(
        `\`watch(fn, options?)\` signature has been moved to a separate api. Use \`watchEffect(fn, options?)\` instead. \`watch\` now only supports \`watch(source, cb, options?) signature.`
      );
    }
    return doWatch(source, cb, options);
  }
function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EMPTY_OBJ) {
  // 代码不完整,截取部分
  ... 
   if (isRef(source)) {
      getter = () => source.value;
      forceTrigger = isshallow(source);
    } else if (isReactive(source)) {
      // 这里 ,如果 source 是 reactive
      // 则 deep = true 
      // 而 deep 为true 后面会 执行traverse
      getter = () => source;
      deep = true;
    } else if (isArray(source)) {
      isMultiSource = true;
      forceTrigger = source.some((s) => isReactive(s) || isShallow(s));
      getter = () => source.map((s) => {
        if (isRef(s)) {
          return s.value;
        } else if (isReactive(s)) {
          return traverse(s);
        } else if (isFunction(s)) {
          return callWithErrorHandling(s, instance, 2 );
        } else {
          warnInvalidSource(s);
        }
      });
    } else if (isFunction(source)) {
      // 如果是函数,
      //最终 getter () => fn()
      // deep为false,因此不走 traverse()
      if (cb) {
        getter = () => callWithErrorHandling(source, instance, 2 );
      } else {
        getter = () => {
          if (instance && instance.isUnmounted) {
            return;
          }
          if (cleanup) {
            cleanup();
          }
          return callWithAsyncErrorHandling(
            source,
            instance,
            3 ,
            [onCleanup]
          );
        };
      }
    } else {
      getter = NOOP;
      warnInvalidSource(source);
    }
    ....
    if (cb && deep) {
      const baseGetter = getter;
      getter = () => traverse(baseGetter());
    }
}

traverse 深度遍历整个对象,深层次的访问其所有的响应式变量,并收集依赖

在自身组件监听 ref 对象

let a = ref({test: 123, bg: 456, hh: {hhh: 78}})
setTimeout(() => {
  a.value.test = 456
}, 2000)
setTimeout(() => {
  a.value.hh.hhh = 56
}, 4000)
setTimeout(() => {
  a.value = {}
}, 6000)
// 注意下面两种写法 一个是 a , 一个是 a.value
// 从源码可知, 如果是 a, 那么走isRef(source)分支, 如果是 a.value 那么走 isReactive(分支)
// 这里不给出结果,动手试试
watch(a.value, (val) => {
  console.log(val, "change")
})
watch(a, (val) => {
  console.log(val, "change")
})
// 如果是 函数返回的方式呢? 其实也分两种,类推即可,同时也需要注意是否需要加 deep 属性
watch(() => a.value, (val) => {
  console.log(val, "change")
})
watch(() => a, (val) => {
  console.log(val, "change")
})

如果在子组件需要监听父组件的数据,同时父组件可以通过v-model双向绑定时需要非常注意,不然可能出现一些bug

如果watch监听无效,根据你的数据结构分析是否是因为写法不正确导致。

总结

到此这篇关于vue3 Watch踩坑实战之watch监听无效的文章就介绍到这了,更多相关Vue3 watch监听无效内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Vue3 Watch踩坑实战之watch监听无效

本文链接: https://www.lsjlt.com/news/212850.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作