Vue Academy · 课时

使用 effectScope 管理分组副作用

使用 effectScope()、在作用域中运行侦听器与计算属性,以及使用 scope.stop() 清理

第 4 / 4 课13 个步骤

使用 effectScope 管理分组副作用 是 CoddyKit 上的免费 Vue Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Vue Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Vue Academy 课程共包含 4 节课。

清理问题

在组件的 setup 外部创建的侦听器和计算值不会自动释放。在独立使用的组合式函数或插件级代码中,您可能会泄漏副作用。effectScope 可以将副作用分组,以便统一清理。

effectScope 的作用

effectScope() 会创建一个作用域,捕获在其中运行期间创建的所有响应式副作用(侦听器、计算值)。之后,您可以停止该作用域,一次性释放它们。

import { effectScope } from "vue"

const scope = effectScope()

使用 run 收集副作用

调用 scope.run(fn),并在 fn 内创建侦听器和计算值。在这次调用期间创建的每个副作用都会注册到该作用域中。

import { effectScope, ref, watch, computed } from "vue"

const scope = effectScope()
scope.run(() => {
  const count = ref(0)
  const doubled = computed(() => count.value * 2)
  watch(count, (v) => console.log(v))
})

停止作用域

scope.stop() 会通过一次调用停止在该作用域内创建的所有侦听器和计算值,无需单独追踪每个 stop 句柄。

scope.stop() // disposes all watchers and computed at once

为什么这很重要

没有作用域时,您必须保存每个侦听器的停止句柄,并逐个调用它们。副作用一多,这种方式就容易出错。作用域可以将 N 次清理合并为一次。

// without scope: must track each
const stop1 = watch(a, fn)
const stop2 = watch(b, fn)
// stop1(); stop2(); ... easy to forget one

嵌套作用域

作用域可以嵌套。在父级作用域内创建的子级作用域,会在父级作用域停止时自动停止,因此您可以免费获得分层清理能力。

const parent = effectScope()
parent.run(() => {
  const child = effectScope() // stopped when parent stops
  child.run(() => watch(/* ... */))
})
parent.stop() // stops child too

脱离作用域

传入 true 可以创建一个脱离的作用域,使其不会被周围的父级作用域收集。当您需要独立控制生命周期时,请使用它。

const scope = effectScope(true) // detached
// must be stopped manually; parent stop will not reach it

使用场景:插件级订阅

一种常见用途是创建位于任何单个组件之外的插件级或应用级响应式订阅,例如将状态库同步到 localStorage。请将它们分组到一个作用域中,并在应用销毁时停止该作用域。

const appScope = effectScope()
appScope.run(() => {
  watch(store.state, persistToLocalStorage, { deep: true })
})
// on app shutdown: appScope.stop()

构建可复用的可释放对象

组合式函数可以创建自己的作用域,将内部副作用打包起来,并公开一个 dispose。调用方只需调用一次,就能清理所有内容。

export function useTracker() {
  const scope = effectScope()
  scope.run(() => {
    watch(/* ... */)
  })
  return { dispose: () => scope.stop() }
}

作用域与组件

在组件的 setup 内部,Vue 已经运行了一个与组件生命周期关联的隐式作用域——这就是组件卸载时其中的侦听器会自动清理的原因。effectScope 让您在组件外部也能获得同样的能力。

getCurrentScope 与 onScopeDispose

在作用域内,您可以使用 onScopeDispose(fn) 注册清理逻辑。作用域停止时,该逻辑就会运行——这类似于 onUnmounted,但适用于任何作用域。

import { onScopeDispose } from "vue"

scope.run(() => {
  const id = setInterval(tick, 1000)
  onScopeDispose(() => clearInterval(id))
})

快速检查

检查您对 effectScope 的理解。

回顾

您学会了使用 effectScope 分组管理副作用:

  • effectScope() 会创建一个作用域,捕获在其中创建的副作用。
  • scope.run(fn) 会收集在 fn 中创建的侦听器和计算值。
  • scope.stop() 会一次性释放所有副作用;嵌套作用域会随父级作用域一起停止(传入 true 可创建脱离的作用域)。
  • onScopeDispose(fn) 会注册在作用域停止时运行的清理逻辑。
  • 它非常适合在组件外部管理组合式函数和插件级响应式订阅。
免费开始

用 AI 导师学习 HTML — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
42
课程
156

常见问题解答

「使用 effectScope 管理分组副作用」课时是免费的吗?

是的 — 「使用 effectScope 管理分组副作用」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Vue Academy 课程的其余内容,请升级到 CoddyKit PRO。 Vue Academy 课程共包含 4 节课。

「使用 effectScope 管理分组副作用」这节课中我会学到什么?

使用 effectScope()、在作用域中运行侦听器与计算属性,以及使用 scope.stop() 清理 你通过在浏览器中直接运行的动手代码来练习 Vue Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Vue Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Vue Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「使用 effectScope 管理分组副作用」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Vue Academy 课中编写并运行代码吗?

能。每节 Vue Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 高级响应式:shallowRef 与 triggerRef
  2. 组合式函数工厂与参数化组合式函数
  3. 在 Vue 中使用 XState 构建状态机
  4. 使用 effectScope 管理分组副作用
← 返回 Vue Academy