当前位置:首页 > VUE

Vue数据依赖实现

2026-03-07 17:53:50VUE

Vue数据依赖实现原理

Vue的数据依赖实现基于响应式系统,核心是通过Object.definePropertyProxy拦截数据读写操作,结合观察者模式完成依赖收集和触发更新。

核心模块分工

响应式系统 通过Observer类递归地将数据对象转换为可观测对象,为每个属性创建Dep实例(依赖收集器)。当属性被访问时触发getter,当前Watcher会被记录到Dep中;当属性修改时触发setter,通知所有关联的Watcher更新。

依赖收集器(Dep) 每个响应式属性对应一个Dep实例,用于存储所有依赖该属性的Watcher。关键方法包括:

  • depend():将当前正在计算的Watcher添加到依赖列表
  • notify():通知所有订阅者执行更新

观察者(Watcher) 作为桥梁连接模板与数据,分为渲染Watcher、计算属性Watcher和用户自定义Watcher。在初始化时会触发get()方法,通过pushTarget()设置全局当前Watcher,触发数据属性的getter完成依赖收集。

实现代码示例

// 简化版Observer实现
class Observer {
  constructor(value) {
    this.value = value
    this.walk(value)
  }

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

// 响应式属性定义
function defineReactive(obj, key, val) {
  const dep = new Dep()
  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) {
        dep.depend()
      }
      return val
    },
    set(newVal) {
      if (newVal === val) return
      val = newVal
      dep.notify()
    }
  })
}

// 依赖收集器
class Dep {
  constructor() {
    this.subs = new Set()
  }

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

  notify() {
    this.subs.forEach(watcher => watcher.update())
  }
}
Dep.target = null

// 观察者
class Watcher {
  constructor(getter) {
    this.getter = getter
    this.value = this.get()
  }

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

  update() {
    this.value = this.get()
  }
}

数组的特殊处理

对于数组类型,Vue通过拦截7个变更方法实现响应式:

const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)
const methodsToPatch = [
  'push', 'pop', 'shift', 'unshift', 
  'splice', 'sort', 'reverse'
]

methodsToPatch.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
  })
})

Vue 3的优化改进

Vue 3使用Proxy替代Object.defineProperty,解决了以下问题:

Vue数据依赖实现

  • 无法检测新增/删除的属性
  • 数组索引修改和长度变化需要特殊处理
  • 减少了递归遍历初始化的性能消耗
function reactive(target) {
  return new Proxy(target, {
    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 界面实现方法 Vue.js 是一个渐进式 JavaScript 框架,用于构建用户界面。以下是实现 Vue 界面的常见方法和技术要点。 安装与项目初始化 使用 Vue CLI 或 Vite…

Vue数据依赖实现

Vue数据依赖实现

Vue数据依赖实现原理 Vue的数据依赖实现基于响应式系统,核心是通过Object.defineProperty或Proxy拦截数据读写操作,结合发布-订阅模式自动追踪依赖和触发更新。 核心机制 依…

vue实现数据删除

vue实现数据删除

Vue 实现数据删除的方法 在 Vue 中删除数据通常涉及操作数组或对象,并结合响应式更新。以下是几种常见实现方式: 从数组中删除数据 使用 splice 方法删除数组中的指定项: methods…

vue实现数据拖动

vue实现数据拖动

Vue 实现数据拖动 使用 HTML5 拖放 API HTML5 提供了原生的拖放 API,可以通过 draggable 属性、dragstart、dragend、dragover 和 drop 事件…

Vue实现lagger页面

Vue实现lagger页面

Vue实现懒加载页面的方法 懒加载(Lazy Loading)是一种优化技术,用于延迟加载非关键资源,从而提升页面初始加载速度。在Vue中可以通过以下方式实现懒加载: 路由懒加载 使用Vue Rou…

vue数据实现

vue数据实现

Vue 数据实现的核心方法 Vue.js 通过数据驱动视图更新,其核心实现基于响应式系统。以下是实现数据绑定的关键方法: 数据声明与响应式原理 在 Vue 2.x 中,使用 Object.defin…