当前位置:首页 > VUE

vue 实现响应式底层

2026-01-22 17:27:41VUE

Vue 响应式原理核心机制

Vue 的响应式系统基于 JavaScript 的 Object.defineProperty(Vue 2)或 Proxy(Vue 3)实现,通过数据劫持结合发布-订阅模式完成依赖收集与更新触发。

数据劫持实现方式

Vue 2 使用 Object.defineProperty 通过递归遍历数据对象,对每个属性设置 getter/setter 拦截操作。当数据被访问时收集依赖,数据变化时通知更新。

function defineReactive(obj, key) {
  let value = obj[key]
  const dep = new Dep() // 依赖收集器

  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) {
        dep.depend() // 收集当前依赖
      }
      return value
    },
    set(newVal) {
      if (newVal === value) return
      value = newVal
      dep.notify() // 触发更新
    }
  })
}

Vue 3 使用 Proxy 直接代理整个对象,无需递归初始化属性,可拦截动态新增属性等操作。

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key) // 追踪依赖
      return Reflect.get(target, key)
    },
    set(target, key, value) {
      Reflect.set(target, key, value)
      trigger(target, key) // 触发更新
      return true
    }
  })
}

依赖收集与派发更新

Dep 类实现 每个响应式属性对应一个 Dep 实例,用于存储所有依赖该属性的 Watcher。

class Dep {
  constructor() {
    this.subscribers = new Set()
  }

  depend() {
    if (Dep.target) {
      this.subscribers.add(Dep.target)
    }
  }

  notify() {
    this.subscribers.forEach(watcher => watcher.update())
  }
}

Watcher 机制 作为观察者,在组件渲染时创建,将自身设置为 Dep.target 以便收集依赖。

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

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

  update() {
    this.run()
  }
}

数组响应式处理

Vue 对数组方法进行特殊处理,重写 pushpop 等变异方法,在保持原生功能的同时触发更新。

vue 实现响应式底层

const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)

['push', 'pop', 'shift'].forEach(method => {
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator(...args) {
    const result = original.apply(this, args)
    const ob = this.__ob__
    ob.dep.notify()
    return result
  })
})

性能优化策略

  • 异步更新队列:通过 nextTick 将多次数据变更合并为单次渲染
  • 虚拟 DOM 比对:减少直接 DOM 操作带来的性能损耗
  • 组件级更新:精确追踪每个组件的依赖关系,避免不必要的子组件更新

响应式系统工作流程

  1. 初始化阶段:递归转换数据为响应式对象,建立属性与 Dep 的关联
  2. 依赖收集阶段:组件渲染触发 getter,将当前 Watcher 注册到对应 Dep
  3. 更新触发阶段:数据变更触发 setter,Dep 通知所有关联 Watcher 更新
  4. 批量更新阶段:通过队列机制异步执行实际 DOM 更新操作

标签: 底层vue
分享给朋友:

相关文章

vue 实现复选

vue 实现复选

Vue 实现复选功能 在 Vue 中实现复选功能可以通过多种方式完成,以下是常见的几种方法: 使用 v-model 绑定数组 通过 v-model 绑定一个数组,可以自动收集用户选择的复选框值。…

vue 实现关闭

vue 实现关闭

Vue 实现关闭功能的方法 在Vue中实现关闭功能通常涉及组件销毁、模态框隐藏或路由跳转等场景。以下是几种常见实现方式: 销毁当前组件 使用v-if或v-show控制组件显示/隐藏,适用于局部组件:…

vue实现hover

vue实现hover

Vue 实现 hover 效果的方法 在 Vue 中实现 hover 效果可以通过多种方式实现,包括使用 CSS、Vue 指令或事件监听。以下是几种常见的方法: 使用 CSS :hover 伪类 通…

vue实现监听

vue实现监听

监听数据变化 在Vue中,可以通过watch选项或$watch方法监听数据的变化。watch适用于组件选项内声明式监听,$watch适用于动态监听。 // 选项式API export default…

vue键盘实现

vue键盘实现

监听键盘事件 在Vue中监听键盘事件可以通过v-on指令或@缩写实现。常见的键盘事件包括keydown、keyup和keypress。例如监听回车键事件: <template> &l…

vue实现表单

vue实现表单

Vue 表单实现方法 双向数据绑定 使用 v-model 指令实现表单元素与数据的双向绑定。适用于 input、textarea、select 等元素。 <template> <…