当前位置:首页 > VUE

vue依赖收集实现

2026-02-18 14:57:10VUE

Vue 依赖收集实现原理

Vue 的依赖收集是通过响应式系统的核心机制实现的,主要涉及 ObserverDepWatcher 三个关键类。

Observer 类

Observer 类负责将对象的属性转换为响应式属性。它通过 Object.definePropertyProxy(Vue 3)拦截属性的读取和修改操作。

vue依赖收集实现

class Observer {
  constructor(value) {
    this.value = value
    this.dep = new Dep()
    if (Array.isArray(value)) {
      // 处理数组
    } else {
      this.walk(value)
    }
  }

  walk(obj) {
    Object.keys(obj).forEach(key => {
      defineReactive(obj, key, obj[key])
    })
  }
}

Dep 类

Dep 是依赖的管理者,每个响应式属性都有一个对应的 Dep 实例。它负责收集依赖(Watcher)并在属性变化时通知这些依赖。

vue依赖收集实现

class Dep {
  constructor() {
    this.subs = []
  }

  addSub(sub) {
    this.subs.push(sub)
  }

  notify() {
    this.subs.forEach(sub => sub.update())
  }

  depend() {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }
}

Watcher 类

Watcher 是依赖的具体实现,它会在初始化时触发属性的 getter,从而将自己添加到 Dep 中。

class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm
    this.getter = parsePath(expOrFn)
    this.cb = cb
    this.value = this.get()
  }

  get() {
    Dep.target = this
    const value = this.getter.call(this.vm, this.vm)
    Dep.target = null
    return value
  }

  addDep(dep) {
    dep.addSub(this)
  }

  update() {
    this.run()
  }

  run() {
    const value = this.get()
    if (value !== this.value) {
      const oldValue = this.value
      this.value = value
      this.cb.call(this.vm, value, oldValue)
    }
  }
}

依赖收集流程

  1. 初始化组件时,会为每个响应式属性创建一个 Observer 实例。
  2. 当属性被访问时(getter 触发),会调用 dep.depend() 将当前 Watcher(Dep.target)添加到 Dep 的订阅列表中。
  3. 当属性被修改时(setter 触发),会调用 dep.notify() 通知所有订阅的 Watcher 进行更新。

示例代码

function defineReactive(obj, key, val) {
  const dep = new Dep()
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      if (Dep.target) {
        dep.depend()
      }
      return val
    },
    set: function reactiveSetter(newVal) {
      if (newVal === val) return
      val = newVal
      dep.notify()
    }
  })
}

Vue 3 的改进

Vue 3 使用 Proxy 替代 Object.defineProperty,依赖收集的实现更加高效:

  • 不需要递归遍历对象的所有属性。
  • 可以监听动态添加的属性。
  • 对数组的操作无需特殊处理。
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      track(target, key)
      return Reflect.get(target, key, receiver)
    },
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver)
      trigger(target, key)
      return true
    }
  })
}

标签: vue
分享给朋友:

相关文章

vue实现防抖节流

vue实现防抖节流

Vue 中实现防抖(Debounce) 防抖的核心是延迟执行函数,在连续触发时取消前一次的调用,只执行最后一次。适用于输入框搜索、窗口大小调整等场景。 方法1:使用 Lodash 的 _.debo…

vue实现下载暂停

vue实现下载暂停

Vue实现下载暂停功能 在Vue中实现下载暂停功能,通常需要结合XMLHttpRequest或Fetch API的AbortController来控制请求中断。以下是具体实现方法: 使用XMLH…

vue实现一个系统

vue实现一个系统

Vue 系统实现步骤 项目初始化与配置 使用 Vue CLI 或 Vite 创建项目: npm init vue@latest my-system 选择需要的配置(Router、Pinia 等)。…

vue请求实现进度条

vue请求实现进度条

实现请求进度条的方法 在Vue中实现请求进度条可以通过多种方式完成,常见的有使用第三方库如axios结合nprogress或自定义进度条组件。以下是几种实现方法: 使用axios和nprogress…

vue实现打印二维码

vue实现打印二维码

安装二维码生成库 使用 qrcode 或 vue-qrcode 库生成二维码。通过 npm 安装: npm install qrcode vue-qrcode 生成二维码 在 Vue 组…

vue实现跑车

vue实现跑车

Vue 实现跑车动画效果 使用 Vue 结合 CSS 动画可以实现跑车在屏幕上移动的效果。以下是一个完整的实现方案: 创建 Vue 组件结构 <template> <div c…