当前位置:首页 > VUE

vue watch实现过程

2026-02-17 16:46:56VUE

Vue 中 watch 的实现过程

Vue 的 watch 功能通过响应式系统的依赖收集和触发机制实现。以下是其核心实现逻辑:

初始化 watch

在组件初始化阶段,Vue 会遍历 watch 选项,为每个监听属性创建对应的 Watcher 实例。这个 Watcher 会被标记为用户 watchuser: true),区别于渲染 Watcher

// 简化后的初始化逻辑
function initWatch(vm, watch) {
  for (const key in watch) {
    const handler = watch[key];
    createWatcher(vm, key, handler);
  }
}

创建 Watcher

Watcher 会解析监听的目标路径(如 a.b.c),并通过 getter 函数建立依赖关系。当被监听的值变化时,触发回调:

// 简化后的 Watcher 创建
new Watcher(vm, getter, callback, { user: true });

依赖收集过程

  1. 首次求值Watcher 会主动执行 getter 函数,访问被监听的数据,触发属性的 get 拦截器。
  2. 依赖记录:在 get 拦截器中,当前 Watcher 会被添加到属性的依赖列表(dep.subs)中。

触发更新

当被监听的数据被修改时:

  1. 属性的 set 拦截器会通知所有依赖的 Watcher
  2. Watcher 执行回调函数,传入新值和旧值。
  3. 如果设置了 immediate: true,回调会在创建 Watcher 时立即执行一次。

深层监听实现

对于 deep: true 的监听:

  1. Watcher 会递归遍历对象的所有属性。
  2. 对每个子属性都触发 get 拦截器,强制收集依赖。
// 简化后的 deep 处理
function traverse(val) {
  if (isObject(val)) {
    for (const key in val) {
      traverse(val[key]);
    }
  }
}

异步队列处理

Vue 通过异步队列(nextTick)批量处理 watch 回调,确保:

vue watch实现过程

  • 多次同步修改只会触发一次回调。
  • 回调执行时 DOM 已更新完毕(与渲染 Watcher 的执行顺序相关)。

与计算属性的区别

  • watch 是主动监听,适合执行副作用(如异步操作)。
  • 计算属性是基于缓存的被动计算,适合派生数据。

性能优化建议

  • 避免过度使用 deep,尤其是监听大型对象。
  • 对于需要监听多个属性的场景,考虑使用 computed 计算后再监听。
  • 必要时使用 unwatch 手动解除监听。

标签: 过程vue
分享给朋友:

相关文章

vue实现菜单

vue实现菜单

Vue 实现菜单的方法 在 Vue 中实现菜单功能可以通过多种方式完成,以下是几种常见的方法: 使用 v-for 动态生成菜单项 通过数据驱动的方式,利用 v-for 指令动态渲染菜单项。定义一个数…

vue实现下载暂停

vue实现下载暂停

Vue实现下载暂停功能 在Vue中实现下载暂停功能,通常需要结合XMLHttpRequest或Fetch API的AbortController来控制请求中断。以下是具体实现方法: 使用XMLHtt…

vue实现groupbox

vue实现groupbox

Vue 实现 GroupBox 组件 在 Vue 中实现类似 GroupBox 的效果可以通过自定义组件完成。GroupBox 通常是一个带有标题的边框容器,用于将相关控件分组显示。 基本实现方法…

vue router实现分页

vue router实现分页

Vue Router 实现分页的方法 在 Vue.js 中,可以通过 Vue Router 实现分页功能,通常需要结合路由参数和动态路由匹配。以下是几种常见的实现方式: 使用查询参数实现分页 在路由…

vue router 实现onshow

vue router 实现onshow

Vue Router 实现 onShow 功能 Vue Router 本身没有直接提供 onShow 这样的生命周期钩子,但可以通过以下方法模拟类似功能。 使用导航守卫 导航守卫可以在路由切换时触发…

vue实现弹层

vue实现弹层

Vue 实现弹层的方法 使用 Vue 原生组件实现弹层 创建一个基础的弹层组件,利用 v-if 或 v-show 控制显示隐藏。 <template> <div class="…