Vue3 watch与watchEffect区别与进阶

16 篇文章 2 订阅
5 篇文章 1 订阅

watch 手动(定向)依赖

watch API 与选项式 API this.$watch (以及相应的 watch 选项) 完全等效。watch 需要侦听特定的数据源,并在单独的回调函数中执行副作用。默认情况下,它也是惰性的——即回调仅在侦听源发生变化时被调用。

特性

  • 惰性地执行;
  • 更具体地说明应触发侦听器重新运行的状态;
  • 访问被侦听状态的先前值和当前值。
  • 可监听单个或多个源数据。
  • 默认不会立即执行。添加 { immediate:true } 可以立即执行,没有惰性。
  • 不可以停止监听。
  • 添加第三个参数 {deep: true} 深度监听。

示例

import { ref, watch } from 'vue'
export default {
	setup() {
	    // 直接侦听一个
		const count = ref(0)
		watch(count, (count, prevCount) => {
		  /* ... */
		}

		// 直接侦听多个
		const fooRef = ref(0);
		const barRef = ref(0);
		watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
		  /* ... */
		},{deep: true})
	    return { count, fooRef, barRef }
	}
}

watchEffect 自动依赖

立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

特性

  • watchEffect不需要指定监听的属性,他会自动的收集依赖, 只要我们回调中引用到了 响应式的属性, 那么当这些属性变更的时候,这个回调都会执行。
  • watchEffect必须立即执行一次(依赖收集);注意: 依赖太多各种坑。
  • 可停止监听。

示例

import { ref, watchEffect } from 'vue'
export default {
	setup() {
	    const count = ref(0)
	    setInterval(() => {
      		count.value++
    	}, 1000)
    	 /** 这个hook用以监听count.value的变化 */
        watchEffect(() => console.log(count.value))
	    // -> logs 0
	    // -> logs 1
	    // -> logs 2
	    // -> logs 3
	    // -> logs 4
	    // -> logs ...
	    return { count }
	}
}

watchEffect 与 watch 有什么不同?

  • 第一点我们可以从示例代码中看到 watchEffect 不需要指定监听的属性,他会自动的收集依赖, 只要我们回调中引用到了 响应式的属性, 那么当这些属性变更的时候,这个回调都会执行,而 watch 只能监听指定的属性而做出变更(v3开始可以同时指定多个)。
  • 第二点就是 watch 可以获取到新值与旧值(更新前的值),而 watchEffect 是拿不到的。
  • 第三点是 watchEffect 如果存在的话,在组件初始化的时候就会执行一次用以收集依赖(与computed同理),而后收集到的依赖发生变化,这个回调才会再次执行,而 watch 不需要,因为他一开始就指定了依赖。

如何选择watch watchEffect,根据以上的不同以及相关业务需求做出正确的选择。

watchEffect 进阶

停止监听

watchEffect 会返回一个用于停止这个监听的函数,如法如下:

import { ref, watchEffect } from 'vue'
export default {
	setup() {
		const stop = watchEffect(() => {
		  /* ... */
		})
		
		// later
		stop()
		return {}
	}
}

如果 watchEffect 是在 setup 或者 生命周期里面注册的话,在组件取消挂载的时候会自动的停止掉。

onInvalidate()

onInvalidate(fn)传入的回调会在 watchEffect 重新运行或者 watchEffect 停止的时候执行。

watchEffect 的第一个参数——effect函数——自己也有参数:叫onInvalidate,也是一个函数,用于清除 effect 产生的副作用。(而且 onInvalidate 的参数也是函数,哈哈!)

onInvalidate 被调用的时机很微妙:它只作用于异步函数,并且只有在如下两种情况下才会被调用:

  • 当 effect 函数被重新调用时
  • 当监听器被注销时(如组件被卸载了)

如下代码中,onInvalidate 会在 id 改变时或停止侦听时,取消之前的异步操作(asyncOperation):

import { asyncOperation } from "./asyncOperation";
 
const id = ref(0);
watchEffect((onInvalidate) => {
  const token = asyncOperation(id.value);
 
  onInvalidate(() => {
    // 如果id 已更改或监视程序已停止,则运行
    token.cancel();
  });
});
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值