写点什么

Vue3 watch 与 watchEffect

作者:程序员海军
  • 2023-04-15
    上海
  • 本文字数:1788 字

    阅读完需:约 6 分钟

Vue3 watch 与 watchEffect

导图大纲


watch

侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数。


watch() 默认是懒侦听的,即仅在侦听源发生变化时才执行回调函数。

watch 有三个参数

第一个参数:

第一个参数是侦听器的源


  • 一个函数,返回一个值

  • 一个 ref

  • 一个响应式对象

  • ...或是由以上类型的值组成的数组

第二个参数

第二个参数是在发生变化时要调用的回调函数。这个回调函数接受三个参数:新值、旧值,以及一个用于注册副作用清理的回调函数。该回调函数会在副作用下一次重新执行前调用,可以用来清除无效的副作用,例如等待中的异步请求。


当侦听多个来源时,回调函数接受两个数组,分别对应来源数组中的新值和旧值。


watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {  /* ... */})
复制代码

第三个参数

第三个可选的参数是一个对象;


  • immediate:在侦听器创建时立即触发回调。第一次调用时旧值是 undefined。

  • deep:如果源是对象,强制深度遍历,以便在深层级变更时触发回调。参考深层侦听器

  • flush:调整回调函数的刷新时机。参考回调的刷新时机watchEffect()

  • onTrack / onTrigger:调试侦听器的依赖。参考调试侦听器

注意

当直接侦听一个响应式对象时,侦听器会自动启用深层模式:

const state = reactive({ count: 0 })watch(state, () => {  /* 深层级变更状态所触发的回调 */})
复制代码

侦听一个 getter 函数:

当 侦听 一个 getter 函数时,回调只在此函数的返回值变化时才会触发,。如果想让深层对象变化时,也被侦听调用,可以加 { deep: true } 强制侦听器进入深层级模式


const state = reactive({ count: 0 })watch(  () => state.count,  (count, prevCount) => {    /* ... */  },  {    deep: true  })
复制代码

侦听 一个 ref

const count = ref(0)watch(count, (count, prevCount) => {  /* ... */})
复制代码

watchEffect()

立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行

watchEffect 接受两个参数

第一个参数

第一个参数是数据发生变化时执行的回调函数


  • 当监听的值发生变化时,会自动再次执行以下回调函数


watchEffect(() => {    //监听objData.str    console.log(objData.str)    // 会在 props 变化时打印    console.log(name, phone, age)    //海军 1234567 22  })
复制代码

第二个参数

第二个参数是一个可选的对象,支持 flush 和 onTrack / onTrigger 选项,功能和 watch 相同。


watchEffect(() => {}, {  flush: 'post',  onTrack(e) {    debugger  },  onTrigger(e) {    debugger  }})
复制代码

停止监听

const stop = watchEffect(() => {})
// 当不再需要此侦听器时:stop()
复制代码

注意

注意:watchEffect 仅会在其同步执行期间,才追踪依赖。使用异步回调时,只有在第一个 await 之前访问到的依赖才会被追踪。

watch vs watchEffect

两者区别

watch 和 watchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式:


  • watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机

  • watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确

访问 Vue 更新之后的 DOM

在 Vue2.x 中, 使用 nextTick, 在 Vue3 中,watch / watchEffect 指明 flush: 'post' 选项 即可。


watch(source, callback, {  flush: 'post'})
watchEffect(callback, { flush: 'post'})
复制代码


watchEffect 有个别名 也可以 后置刷新 watchPostEffect();


import { watchPostEffect } from 'vue'
watchPostEffect(() => { /* 在 Vue 更新后执行 */})
复制代码

小技巧

关闭监听器

手动停止一个侦听器,请调用 watch 或 watchEffect 返回的函数:


const stopWatchEffect = watchEffect(() => {})

stopWatchEffect()


const stopWatch = watch(() => {})

stopWatch()
复制代码

异步数据加载

如果需要等待一些异步数据,你可以使用条件式的侦听逻辑:


// 需要异步请求得到的数据const data = ref(null)
watchEffect(() => { if (data.value) { // 数据加载后执行某些操作... }})
复制代码

参考链接🔗:

https://cn.vuejs.org/guide/essentials/watchers.html

https://www.51cto.com/article/719098.html

发布于: 刚刚阅读数: 3
用户头像

🏆微信公众号:【前端自学社区】 2020-04-02 加入

🏅目前从事物流,铁路相关的前端全栈开发工作. 🏆 InfoQ 首批签约作者 🏆荣获2021/2022年度社区共建奖 😊个人微信: daxin261

评论

发布
暂无评论
Vue3 watch 与 watchEffect_Vue_程序员海军_InfoQ写作社区