当前位置:首页 > VUE

vue依赖收集实现

2026-02-18 14:57:10VUE

Vue 依赖收集实现原理

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

Observer 类

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

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)并在属性变化时通知这些依赖。

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,依赖收集的实现更加高效:

vue依赖收集实现

  • 不需要递归遍历对象的所有属性。
  • 可以监听动态添加的属性。
  • 对数组的操作无需特殊处理。
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中实现穿梭框组件,可以使用<el-transfer>(Element UI)或手动实现。以下是手动实现的核心逻辑: <template> &l…

vue实现打印

vue实现打印

使用Vue实现打印功能 在Vue项目中实现打印功能可以通过多种方式完成,以下是几种常见的方法: 方法一:使用window.print() 这种方法适用于打印整个页面或特定区域的内容。 // 在Vu…

vue sku 实现

vue sku 实现

Vue SKU 实现方案 在电商系统中,SKU(Stock Keeping Unit)是商品的最小库存单位,通常由多个属性组合而成(如颜色、尺寸等)。以下是基于 Vue 的实现方案。 数据结构设计…

vue逻辑实现怎么实现

vue逻辑实现怎么实现

Vue 逻辑实现方法 Vue 的逻辑实现主要通过组件化、响应式数据、计算属性、方法、生命周期钩子等方式完成。以下是一些核心实现方法: 数据驱动与响应式 在 Vue 中,通过 data 选项定义响应式…

vue实现选择框

vue实现选择框

Vue 实现选择框的方法 Vue 中可以通过多种方式实现选择框(下拉框),包括原生 HTML 的 <select> 元素结合 Vue 的数据绑定,或者使用第三方 UI 库如 Element…

vue实现全选下载

vue实现全选下载

Vue实现全选下载功能 全选下载功能通常涉及前端文件列表的多选操作和批量下载逻辑。以下是基于Vue的实现方案: 数据准备与渲染 在Vue组件中定义文件列表数据和选中状态: data() { r…