当前位置:首页 > 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 中实现页签功能通常涉及动态组件、路由或状态管理。以下是几种常见的实现方式: 使用动态组件 通过 Vue 的 <component> 动态组件结合 v-…

vue 实现blog

vue 实现blog

Vue 实现博客的基本步骤 使用 Vue 实现博客可以分为前端和后端两部分,前端使用 Vue.js 框架,后端可以选择 Node.js、Python 或其他服务端语言。以下是一个基于 Vue 的博客实…

vue实现switch

vue实现switch

Vue 实现 Switch 开关组件 在 Vue 中实现 Switch 开关组件可以通过自定义组件或使用现有 UI 库完成。以下是几种常见实现方式: 自定义 Switch 组件 创建一个基础 Sw…

vue页面实现

vue页面实现

Vue 页面实现方法 创建 Vue 组件 使用 Vue 单文件组件(SFC)方式创建页面,文件扩展名为 .vue。一个基本的 Vue 组件包含三个部分:模板(template)、脚本(script)和…

vue实现标签

vue实现标签

Vue 实现标签的方法 在 Vue 中实现标签功能可以通过多种方式完成,以下是几种常见的方法: 使用动态组件 动态组件可以根据不同的条件渲染不同的标签内容。通过 :is 属性动态绑定组件名,实现标…

vue轮询实现

vue轮询实现

Vue 轮询实现方法 在 Vue 中实现轮询可以通过以下几种方式: 使用 setInterval data() { return { pollInterval: null } },…