当前位置:首页 > 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 等变异方法,在保持原生功能的同时触发更新。

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 实现滚动中断的方法 在 Vue 中实现滚动中断通常涉及监听滚动事件,并在特定条件下阻止默认行为或停止滚动。以下是几种常见方法: 监听滚动事件并阻止默认行为 通过 @scroll 或 @whe…

vue实现皮肤切换

vue实现皮肤切换

实现皮肤切换的基本思路 在Vue中实现皮肤切换功能,通常涉及动态修改CSS变量或类名。核心是通过状态管理当前主题,并在组件中应用对应的样式。 使用CSS变量实现主题切换 CSS变量(自定义属性)是…

vue前端实现注册

vue前端实现注册

使用 Vue 实现用户注册功能 环境准备 确保已安装 Vue CLI 或通过 CDN 引入 Vue。若使用 Vue CLI,需安装 axios 或其他 HTTP 库用于后端通信。 注册表单组件 创…

vue播放倍速怎么实现

vue播放倍速怎么实现

实现Vue播放倍速的方法 在Vue中实现播放倍速功能通常涉及HTML5的<video>元素或第三方播放器库。以下是几种常见实现方式: 使用原生HTML5 video元素 通过ref获取…

vue实现弹窗

vue实现弹窗

Vue 实现弹窗的常见方法 使用组件化方式封装弹窗 创建一个独立的弹窗组件(如 Modal.vue),通过 v-if 或 v-show 控制显示隐藏: <template> <…

vue实现点击

vue实现点击

实现点击事件的基本方法 在Vue中实现点击事件可以通过v-on指令或@简写方式绑定。以下是常见的点击事件绑定方法: <template> <button v-on:click=…