回首Vue3之API篇(十)

1,662 阅读3分钟

这是我参与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"
})

侦听多个时,会以数组的形式作为参数。另外我们需要注意的是:

watchwatchEffect手动停止副作用无效 (将 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

总结

  1. 对于computed,在项目中我们一般使用简写的方式就已经满足我们的需求了,非必要不用全写的方式。

  2. watchEffectwatch我们要根据需求去合理的使用它们。

  3. 新增的API,一般情况我们可能用不到,但是当你需要对一些行为做项目的操作的时候,可以使用它们。

想了解更多文章,传送门已开启:回首Vue3目录篇