这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战
这篇文章我们来讲一下Computed 与 watch以及Vue3.2新增的一些响应性API的使用,以及我们需要注意的地方。
如何使用
computed
在Vue2中是计算属性,在Vue3中是计算方法,其实它们的作用都是一样得,只不过用法有些差异,此时computed的用法如下:
简写
const count = ref(1)
const plusOne = computed(() => count.value + 1)
接受一个 getter 函数,并为从 getter 返回的值返回一个不变的响应式 ref 对象。此时,count改变的时候,plusOne也会随之加一。
全写
const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1
}
})
它也可以使用具有 get 和 set 函数的对象来创建可写的 ref 对象。此时,count改变的时候,plusOne会随之加一;plusOne改变的时候,count也会随之减一。
值得我们注意的是:在我们实际开发中,如果只是单纯的使用count,那我们简写就足够了;如果需要在改变plusOne的值时候做一下操作,那我们只能用全写模式。
watchEffect
为了根据响应式状态自动应用和重新应用副作用,我们可以使用 watchEffect 方法。它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。使用如下:
const count = ref(1)
const stop = watchEffect(() => console.log(`output log:${count.value}`))
当count的值发生变化的时候,都会触发这个副作用函数,也就是说会打印出:output log:?。那么如何停止这个副作用的侦听呢?虽然在组件卸载时 watchEffect会自动停止,但是我们也可以手动停止,如下:
stop()
既然我们都可以把副作用的侦听给停止了,那么我们应该可以把副作用给清除了。官方说,侦听副作用传入的函数可以接收一个 onInvalidate 函数作入参,用来注册清理失效时的回调。我们如果来使用呢,假定我们有这样一个需求:
一个获取数据的api,传参是id,每次id变化的时候,我们都会发生一次请求,那么我们只想获取一次怎么办呢,在这里我们就可以把副作用给清除了,如下:
watchEffect(onInvalidate => {
const token = getData(id)
onInvalidate(() => {
token.cancel()
})
})
watchPostEffect 和 watchSyncEffect
这两个api是Vue3.2新增的方法,相当于给watchEffect增加了一个参数,目前使用的不多,后面用到再加以更新详述。
watch
watch API 与选项式 API this.$watch 作用是一样的,watch 需要侦听特定的数据源,并在单独的回调函数中执行副作用。默认情况下,它也是惰性的,与watchEffect比较,watch 允许我们:
- 惰性地执行副作用;
- 更具体地说明应触发侦听器重新运行的状态;
- 访问被侦听状态的先前值和当前值。
使用方法如下:
侦听一个单一源
// 侦听一个 getter
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {"dosomething"}
)
// 直接侦听一个 ref
const count = ref(0)
watch(count, (count, prevCount) => {"dosomething"})
侦听多个源
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
"dosomething"
})
侦听多个时,会以数组的形式作为参数。另外我们需要注意的是:
watch与watchEffect在手动停止,副作用无效 (将 onInvalidate 作为第三个参数传递给回调),flush timing 和 debugging 方面有相同的行为。
effectScope
Effect scope 是一种高级 API,主要供库作者使用。创建一个效果范围对象,该对象可以捕获在其中创建的反应性效果(例如计算和观察者),以便可以将这些效果放在一起,如下:
const scope = effectScope()
scope.run(() => {
const doubled = computed(() => counter.value * 2)
watch(doubled, () => console.log(doubled.value))
watchEffect(() => console.log('Count: ', doubled.value))
})
// 停止这个作用域内的所有影响
scope.stop()
我们可以利用effectScope来批量的处理一些操作。
getCurrentScope
获取当前作用域内容,也就是上述的effectScope,其函数如下:
function getCurrentScope(): EffectScope | undefined
onScopeDispose
在当前作用域上注册一个回调函数,这个回调函数会在effectScope停止的时候调用,其函数如下:
function onScopeDispose(fn: () => void): void
总结
-
对于
computed,在项目中我们一般使用简写的方式就已经满足我们的需求了,非必要不用全写的方式。 -
watchEffect与watch我们要根据需求去合理的使用它们。 -
新增的API,一般情况我们可能用不到,但是当你需要对一些行为做项目的操作的时候,可以使用它们。
想了解更多文章,传送门已开启:回首Vue3目录篇 !