Vue3.2 新正式属性 Effect Scope API -- Vue

本文介绍了在Vue3中如何在组件外部或独立包中管理并停止computed和watch的响应式依赖。通过EffectScopeAPI,可以更方便地控制响应式效果的开启和关闭。当调用scope.stop()时,所有在run内定义的计算属性的依赖将停止更新,避免了手动维护停止函数数组的繁琐操作。
摘要由CSDN通过智能技术生成

一起学习Vue,关注我,不迷路~

在Vue的setup中,响应会在开始初始化的时候被收集,在实例被卸载的时候,响应就会自动的被取消追踪了,这时一个很方便的特性。
但是,当我们在组件外使用或者编写一个独立的包时,这会变得非常麻烦。当在单独的文件中,我们该如何停止computed & watch的响应式依赖呢?

//(vue-RFC示例代码)
const disposables = []

const counter = ref(0)
const doubled = computed(() => counter.value * 2)

disposables.push(() => stop(doubled.effect))

const stopWatch1 = watchEffect(() => {
  console.log(`counter: ${counter.value}`)
})

disposables.push(stopWatch1)

const stopWatch2 = watch(doubled, () => {
  console.log(doubled.value)
})

disposables.push(stopWatch2)

代码解读:
上面的代码中,我们写了一共三个计算属性,把这些就算属性的stopHandle都存到一个数组中,意思是我们需要维护这个数组,这样将来在需要的时候,就可以像下面这样,直接把所有的响应都停掉:

//(vue-RFC示例代码)
disposables.forEach((f) => f())
disposables = []

上面我们调用了数组中的每一个stopHandle,停止了所有的响应。
但是这样我们每定义一个计算属性,都需要加入到这个数组中,是不是很麻烦?

所以,在Vue3.2中,新的API-----Effect Scope API出现了,专门用来解决这个问题。
首先,effectScope是一个函数,调用effectScope函数会返回一个对象,其中包含了run(一个函数)和stop(一个函数);

//(vue-RFC示例代码)
function effectScope(detached?: boolean): EffectScope

interface EffectScope {
  run<T>(fn: () => T): T | undefined // undefined if scope is inactive
  stop(): void
}

我们可以像下面这样使用它。(vue-RFC示例代码)

//(vue-RFC示例代码)
const scope = effectScope()

scope.run(() => {
  const doubled = computed(() => counter.value * 2)

  watch(doubled, () => console.log(doubled.value))

  watchEffect(() => console.log('Count: ', doubled.value))
})

// to dispose all effects in the scope
scope.stop()

这样,在run中定义的所有计算属性,在调用了scope对象的stop()方法之后,所有的依赖都被停止了。

做个实验:

const scope = effectScope()
let counter = ref(0)
setInterval(() => {
  counter.value++
}, 1000);
scope.run(() => {
  watchEffect(() =>console.log(`counter: ${counter.value}`))
})
/*log:
counter: 0
counter: 1
counter: 2
counter: 3
counter: 4
counter: 5
*/

我们不停止,浏览器会一直输出conter的值:

const scope = effectScope()
let counter = ref(0)
setInterval(() => {
  counter.value++
}, 1000);
scope.run(() => {
  watchEffect(() =>console.log(`counter: ${counter.value}`))
})
scope.stop()
/*log:
counter: 0
*/

但当我们调用了stop之后,浏览器只会输出一次。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值