当前位置:首页 > VUE

vue watch实现原理

2026-03-09 05:16:29VUE

Vue 中 watch 的实现原理

Vue 的 watch 功能基于响应式系统的依赖收集和触发机制实现。其核心原理可分为以下几个部分:

依赖收集与响应式系统

Vue 通过 Object.definePropertyProxy(Vue 3)拦截数据的读取和修改操作。当在 watch 中监听一个属性时,会触发该属性的 getter,从而将当前 watcher 添加到依赖列表中。

// 简化版依赖收集逻辑
function defineReactive(obj, key, val) {
  const dep = new Dep() // 依赖管理器
  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) { // 当前正在计算的watcher
        dep.addSub(Dep.target)
      }
      return val
    },
    set(newVal) {
      val = newVal
      dep.notify() // 通知所有依赖的watcher更新
    }
  })
}

Watcher 类的作用

watch 的每个监听项会创建一个 Watcher 实例。当监听的值变化时,Watcher 会执行回调函数或重新计算表达式。

class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm
    this.getter = parsePath(expOrFn) // 解析属性路径(如"a.b.c")
    this.cb = cb
    this.value = this.get()
  }

  get() {
    Dep.target = this // 设置当前watcher
    const value = this.getter.call(this.vm, this.vm) // 触发getter收集依赖
    Dep.target = null
    return value
  }

  update() {
    const oldValue = this.value
    this.value = this.get()
    this.cb.call(this.vm, this.value, oldValue) // 执行回调
  }
}

异步更新队列

Vue 通过异步队列(nextTick)优化多次数据变更的触发效率。当监听的属性变化时,watcher 不会立即执行回调,而是被推入队列,在下一个事件循环中统一执行。

// 简化版更新队列
const queue = []
let waiting = false

function queueWatcher(watcher) {
  if (!waiting) {
    waiting = true
    nextTick(flushQueue)
  }
  queue.push(watcher)
}

function flushQueue() {
  queue.forEach(watcher => watcher.run())
  queue.length = 0
  waiting = false
}

深度监听实现

当设置 deep: true 时,Watcher 会递归遍历对象的所有属性,强制触发它们的 getter 以收集深层依赖:

vue watch实现原理

function traverse(val) {
  if (typeof val !== 'object') return
  for (const key in val) {
    traverse(val[key]) // 递归访问子属性
  }
}

与计算属性的区别

  • watch 允许执行异步操作,适合数据变化时需要执行副作用(如请求API)的场景。
  • 计算属性基于缓存机制,只有依赖变化时才重新计算,适合同步派生数据的场景。

性能优化建议

  • 避免监听复杂嵌套对象,必要时使用 deep 配合特定路径监听。
  • 对于频繁变化的场景,可使用 immediate: true 立即获取初始值。
  • 在组件销毁前通过 unwatch() 手动移除不必要的监听。

标签: 原理vue
分享给朋友:

相关文章

vue alert实现

vue alert实现

使用 Vue 实现 Alert 组件 在 Vue 中实现 Alert 组件可以通过自定义组件或结合第三方库完成。以下是几种常见方法: 自定义 Alert 组件 创建一个可复用的 Alert 组件,通…

vue实现图片

vue实现图片

Vue 实现图片功能的方法 静态图片引入 在 Vue 项目中,可以通过 src 属性直接引入静态图片。图片通常放在 public 或 assets 目录下。 <template> &…

vue实现水印

vue实现水印

Vue 实现水印的方法 使用 CSS 背景图 通过 CSS 的 background-image 和 background-repeat 属性实现水印效果。创建一个包含水印文本的 Canvas,将其转…

vue 实现轮播

vue 实现轮播

Vue 实现轮播的方法 使用第三方库(如 Swiper) 安装 Swiper 库: npm install swiper 在 Vue 组件中引入 Swiper: <template&…

js 实现vue

js 实现vue

实现 Vue 的核心功能 在 JavaScript 中实现 Vue 的核心功能需要模拟数据绑定、虚拟 DOM 和响应式系统。以下是一个简化版的实现思路: 响应式系统 通过 Object.define…

vue sku 实现

vue sku 实现

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