全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-20 7 分钟 ✍️ juanwangdev

依赖收集与触发

响应式系统的核心机制是依赖收集(track)与依赖触发(trigger),实现数据与视图的绑定。

Dep 与 Watcher

JavaScript
let uid = 0

class Dep {
  constructor() {
    this.id = uid++
    this.subs = []
  }
  addSub(sub) {
    this.subs.push(sub)
  }
  depend() {
    if (Dep.target) this.addSub(Dep.target)
  }
  notify() {
    this.subs.slice().forEach(sub => sub.update())
  }
}

Dep.target = null

依赖收集过程

数据被读取时触发 getter,收集当前活跃的 Watcher:

JavaScript
function defineReactive(obj, key, val) {
  const dep = new Dep()
  Object.defineProperty(obj, key, {
    get() {
      // 组件渲染时,全局 Dep.target 指向当前 Watcher
      if (Dep.target) {
        dep.depend() // 收集依赖
      }
      return val
    },
    set(newVal) {
      val = newVal
      dep.notify() // 触发更新
    }
  })
}

Watcher 类

JavaScript
class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm
    this.cb = cb
    this.getter = typeof expOrFn === 'function' ? expOrFn : () => vm[expOrFn]
    this.value = this.get()
  }
  get() {
    Dep.target = this
    const value = this.getter.call(this.vm)
    Dep.target = null
    return value
  }
  update() {
    const oldValue = this.value
    this.value = this.get()
    this.cb.call(this.vm, this.value, oldValue)
  }
}

Vue 3 的 track 与 trigger

Vue 3 使用 WeakMap + Map + Set 存储依赖关系:

JavaScript
const targetMap = new WeakMap()

function track(target, key) {
  if (!Dep.target) return
  let depsMap = targetMap.get(target)
  if (!depsMap) targetMap.set(target, (depsMap = new Map()))
  let dep = depsMap.get(key)
  if (!dep) depsMap.set(key, (dep = new Set()))
  dep.add(Dep.target)
}

function trigger(target, key) {
  const depsMap = targetMap.get(target)
  if (!depsMap) return
  const dep = depsMap.get(key)
  if (dep) dep.forEach(effect => effect())
}

计算属性的依赖缓存

JavaScript
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
// firstName 和 lastName 的 getter 执行时收集了 computed 作为依赖
// 只有两者之一变化时,fullName 才会重新计算

要点总结

  • getter 中调用 dep.depend() 收集当前 Watcher
  • setter 中调用 dep.notify() 通知所有 Watcher 更新
  • Vue 2 使用 Dep + Watcher 类实现
  • Vue 3 使用 WeakMap 存储依赖关系,更高效的 track/trigger

📝 发现内容有误?点击此处直接编辑

← 上一篇 事件处理优化
下一篇 → 响应式原理
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库