当前位置:首页 > VUE

vue watch 实现 原理

2026-01-15 05:06:48VUE

Vue Watch 实现原理

Vue 的 watch 功能用于监听数据变化并执行回调函数。其核心原理基于 Vue 的响应式系统,依赖 Object.definePropertyProxy(Vue 3)实现数据劫持,并结合依赖收集和派发更新机制。

响应式系统基础

Vue 的响应式系统通过以下步骤实现:

  1. 数据劫持:使用 Object.defineProperty(Vue 2)或 Proxy(Vue 3)拦截数据的读取和修改操作。
  2. 依赖收集:在数据被访问时,收集当前正在计算的依赖(如 watch 回调)。
  3. 派发更新:在数据被修改时,通知所有依赖执行更新。

Watch 的工作流程

  1. 初始化阶段
    当在 Vue 实例中定义 watch 时,Vue 会遍历 watch 的配置项,为每个被监听的数据创建一个 Watcher 实例。

    new Vue({
      data: { count: 0 },
      watch: {
        count(newVal, oldVal) {
          console.log('count changed:', oldVal, '->', newVal);
        }
      }
    });
  2. 依赖收集
    Watcher 实例会在初始化时调用 get 方法,触发被监听数据的 getter,从而将当前 Watcher 添加到依赖列表中(Dep 的 subs 数组)。

  3. 数据变化触发回调
    当被监听的数据被修改时,会触发 setterProxy 的拦截逻辑,通知依赖列表中的所有 Watcher 执行 update 方法。
    Watcherupdate 方法会调用回调函数,并传入新值和旧值。

    vue watch 实现 原理

源码核心逻辑(Vue 2)

  1. Watcher 类
    Watcherwatch 的核心实现,负责管理依赖和回调执行。

    class Watcher {
      constructor(vm, expOrFn, cb, options) {
        this.vm = vm;
        this.cb = cb;
        this.getter = parsePath(expOrFn); // 解析监听路径(如 'a.b.c')
        this.value = this.get(); // 初始化时触发依赖收集
      }
    
      get() {
        pushTarget(this); // 将当前 Watcher 设置为全局正在计算的依赖
        const value = this.getter.call(this.vm, this.vm); // 触发 getter
        popTarget(); // 恢复之前的依赖
        return value;
      }
    
      update() {
        const oldValue = this.value;
        this.value = this.get(); // 重新获取值
        this.cb.call(this.vm, this.value, oldValue); // 执行回调
      }
    }
  2. 依赖管理(Dep 类)
    每个响应式数据属性都有一个 Dep 实例,用于管理依赖。

    class Dep {
      constructor() {
        this.subs = []; // 存储 Watcher 实例
      }
    
      depend() {
        if (Dep.target) {
          this.subs.push(Dep.target); // 收集依赖
        }
      }
    
      notify() {
        this.subs.forEach(watcher => watcher.update()); // 通知更新
      }
    }

深度监听和立即执行

  1. 深度监听(deep: true)
    通过递归遍历对象的所有属性,为每个子属性绑定 Watcher

    vue watch 实现 原理

    if (this.deep) {
      traverse(value); // 递归触发子属性的 getter
    }
  2. 立即执行(immediate: true)
    Watcher 初始化时直接调用回调。

    if (options.immediate) {
      cb.call(vm, this.value);
    }

Vue 3 的改进

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

  • 无需递归劫持对象,Proxy 可以动态监听新增属性。
  • 性能更好,避免了 Vue 2 中全量递归的缺陷。

总结

Vue 的 watch 机制依赖于响应式系统的核心设计:

  • 通过 WatcherDep 管理依赖关系。
  • 数据变化时触发 Watcher 回调。
  • 支持深度监听和立即执行等高级功能。

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

相关文章

vue实现选中单元格

vue实现选中单元格

Vue 实现选中单元格的方法 基础实现思路 在 Vue 中实现选中单元格功能,通常可以通过动态绑定 class 或 style 来实现。以下是一个基于表格的简单实现示例: <templ…

vue实现modal

vue实现modal

Vue 实现 Modal 弹窗组件 使用 Vue 实现 Modal 弹窗组件可以通过多种方式,包括原生 Vue 组件、第三方库或自定义指令。以下是几种常见方法: 原生 Vue 组件实现 创建一个基础…

vue实现计算

vue实现计算

Vue 实现计算的方法 在 Vue 中实现计算功能可以通过多种方式完成,主要包括计算属性(computed)、方法(methods)和侦听器(watch)。以下是具体的实现方法: 计算属性(Comp…

vue实现海报

vue实现海报

Vue 实现海报生成方案 使用 html2canvas 库 html2canvas 是一个将 HTML 元素转换为 Canvas 的库,适合将 Vue 组件渲染为海报图片 安装依赖: npm…

vue实现水印

vue实现水印

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

vue实现波形

vue实现波形

实现波形效果的方法 在Vue中实现波形效果可以通过多种方式完成,常见的方法包括使用Canvas绘制、CSS动画或第三方库。以下是几种实现方案: 使用Canvas绘制波形 通过Canvas API动态…