watch VS watchEffect

目录

如何使用 watch ?

如何在首次监听后,自动取消 watch 监听? 

如果需要跟踪多个响应式变量,有什么好的解决方案吗?

watchEffect VS watch

是否需要指手动传入依赖

是否为惰性的

每次监听依赖项时 返回的值

watchEffect VS computed

如何使用 watchEffect ?

使用 onInvalidate() 清除 watchEffect 副作用

使用 watchEffect 返回的 stop 方法,停止 watchEffect 监听

使用 flush 修改 watchEffect 监听的时机


如何使用 watch ?

Vue Options API 提供了一个 watch 选项

export default {
  data () {
    return {
      title: 'Vue2'
    }
  },
  watch: {
    // Watcher
  }
}

  watch: {
    title: {
      handler: (newTitle, oldTitle) => {
        console.log("Title changed from " + oldTitle + " to " + newTitle);
      },
      immediate: true,
    },
  },

适用场景:

  • 需要控制哪些依赖项会触发该方法
  • 需要访问之前的值

如何在首次监听后,自动取消 watch 监听? 

调用 watch 自身,可以实现此需求

/**
 * 监听 vuex 里开发者配置改变
 */
const watchInitData = watch(
  () => store.state[VuexModule.ApplicationLibDevelopment],
  async (newVal) => {
    // 页面初始化
    initPage();
    // 调用 watch 本身,可以实现取消监听
    watchInitData();
  },
  { deep: true },
);

如果需要跟踪多个响应式变量,有什么好的解决方案吗?

在 Vue Options API(Vue2)中,可以创建多个 watch 观察者

在 Composition API(Vue3)中,可以创建多个  watchEffect 观察者;也可以只创建一个 watchEffect,但在他的回调函数中,写上所有要监听的值

watchEffect VS watch

是否需要指手动传入依赖

watch —— 既要指明监视的属性,也要指明监视的回调【需要手动传入依赖】

watchEffect —— 不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性【不需要手动传入依赖,会从回调函数中自动获取】

是否为惰性的

watch 是惰性的 —— 仅当依赖项更改时,才会触发;可以为 watch 传递一个 immediate 属性,使其在初始化时运行

watchEffect 是非惰性的 —— 在创建组件后立即运行,同时,在方法的任何依赖项发生更改时运行

每次监听依赖项时 返回的值

wach —— 每次监听,都会返回新旧值

watchEffect —— 每次监听,只会返回最新的值;只有在页面初始化时,才能拿到一次旧值

watchEffect VS computed

watchEffect 和 watch 一样,都有点像 computed

  • computed 注重的计算出来的值(回调函数的返回值),所以必须要写返回值
  • watchEffect 注重的是过程(回调函数的函数体),所以不用写返回值

如何使用 watchEffect ?

  • 在初始化组件时立即运行(组件初始化时,watchEffect 将运行并记录起始值)
  • 在依赖项发生变化时运行(当 监听对象的值 改变时,就会触发 watchEffect)

由第二点可得:在挂载 DOM 之前,尽量不要尝试访问 DOM,防止产生不必要的监听

import { ref, watchEffect } from 'vue'

export default {
  setup () {
    const userID = ref(233)

    watchEffect(() => console.log('userID: ' + userID.value))
    
    setTimeout(() => {
      userID.value = 666
    }, 500)

    return {
      userID
    }
  }
}

// 打印结果
userID: 233
userID: 666

也可以在组件中,使用 watchEffect 结合 props 进行使用

export default {
  props: {
    movieID: String,
  },
  setup(props) {
    watchEffect(() => console.log(props.movieID))
  },
}

使用 onInvalidate() 清除 watchEffect 副作用

每当 watchEffect 监听到了依赖项变化时,就执行一个异步请求;

但是在异步请求完成之前,依赖项又发生了变化……

如何避免再一次发请求?

export default {
  setup() {
    watchEffect(onInvalidate => {
      // 异步请求
      const apiCall = someAsyncMethod(props.songID)

      onInvalidate(() => {
        // 取消异步请求
        apiCall.cancel()
      })
    })
  }
}

使用 watchEffect 返回的 stop 方法,停止 watchEffect 监听

可以手动停止 watchEffect 监听

试想一下,如果你想观察一个依赖项,直到他变成某个值,就不希望继续监听了

继续监听属于浪费资源了,如何实现手动停止 watchEffect 监听?

watchEffect 返回了 stop 方法,调用它,可以手动停止 watchEffect 监听

export default {
  setup (props) {
    let stopWatcher = watchEffect(() => console.log(props.movieID))
    stopWatcher()
  }
}

使用 flush 修改 watchEffect 监听的时机

watchEffect 默认在组件加载好之前,就会调用一次监听,举个栗子:

const state = reactive({
  test: {
    myName: '',
  }
});

state.test.myName = 'Lyrelion' 

watchEffect(() => {
  console.log('名字被修改了', state.test.myName );
})

/**
 * 打印结果(在组件更新前,watchEffect 就执行了一次监听,所以会打印两次)
 * 名字被修改了 
 * 名字被修改了 Lyrelion
 */

如果在组件加载好之前,我不想执行监听呢?也就是说,修改 watchEffect 监听时机

可以通过修改 watchEffect 中的 flush 属性,指定监听时机

flush 有以下三种可设置项:

  • pre (默认)
  • post (在组件渲染完成后触发,访问加载后的 DOM,这就可以防止初始值还没附上,就开始监听了的问题)
  • sync (与 watch 一样,每个更改都强制触发侦听器,这是低效的,应该很少需要)

综上所述,为了在组件加载好之前,不执行监听,可以这么写

const state = reactive({
  test: {
    myName: '',
  }
});

state.test.myName = 'Lyrelion' 

watchEffect(() => {
  console.log('名字被修改了', state.test.myName );
}, {
  flush: 'post'
})

/**
 * 打印结果(在组件更新前,watchEffect 就执行了一次监听,所以会打印两次)
 * 名字被修改了 Lyrelion
 */

补充一篇写的不错的文章

VUE3中watch与watchEffect —— 全网最详细系列_海底烧烤店ai的博客-CSDN博客_watch和watcheffectVUE3——watch与watchEffect详解一、 watchEffect1. 停止监听2. 更改监听时机(更改副作用刷新时机)3. 清除副作用4. 侦听器调试一、watch1. 监听单一源2. 监听多个源3. 侦听响应式对象4. 深度监听5. 立即执行在讲watch之前,我们先来看看watchEffect一、 watchEffect立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。watchEffect的一些特点:不需要手动传入依赖(不用指定监听对象)无https://blog.csdn.net/m0_51969330/article/details/123673334?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-123673334-blog-112723178.pc_relevant_multi_platform_whitelistv3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-123673334-blog-112723178.pc_relevant_multi_platform_whitelistv3&utm_relevant_index=2

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyrelion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值