当前位置:首页 > VUE

vue响应式实现

2026-02-25 14:38:47VUE

Vue 响应式实现原理

Vue 的响应式系统基于 JavaScript 的 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)实现,核心是通过数据劫持和依赖收集来自动追踪数据变化并更新视图。

Vue 2.x 实现方式

数据劫持 通过 Object.defineProperty 递归地将对象的属性转换为 getter/setter,从而在属性被访问或修改时触发拦截。

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log(`访问 ${key}`);
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        console.log(`修改 ${key} 为 ${newVal}`);
        val = newVal;
      }
    }
  });
}

依赖收集 每个响应式属性关联一个 Dep(依赖管理器),在 getter 中收集依赖(Watcher),在 setter 中通知依赖更新。

vue响应式实现

class Dep {
  constructor() {
    this.subscribers = [];
  }
  depend() {
    if (target && !this.subscribers.includes(target)) {
      this.subscribers.push(target);
    }
  }
  notify() {
    this.subscribers.forEach(sub => sub());
  }
}

let target = null;
function watchEffect(effect) {
  target = effect;
  effect();
  target = null;
}

Vue 3.x 实现方式

Proxy 代理 使用 Proxy 拦截对象的整个操作(包括新增/删除属性),无需递归遍历对象。

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key);
      return target[key];
    },
    set(target, key, value) {
      target[key] = value;
      trigger(target, key);
      return true;
    }
  });
}

依赖跟踪与触发 通过 tracktrigger 函数管理依赖关系,替代 Vue 2.x 的 DepWatcher

vue响应式实现

const targetMap = new WeakMap();
function track(target, key) {
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()));
  }
  let dep = depsMap.get(key);
  if (!dep) {
    depsMap.set(key, (dep = new Set()));
  }
  dep.add(activeEffect);
}

function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;
  depsMap.get(key).forEach(effect => effect());
}

响应式系统的局限性

对象新增属性 Vue 2.x 中直接通过 obj.newKey = value 添加的属性不是响应式的,需使用 Vue.setthis.$set

数组变更检测 Vue 2.x 无法检测以下数组变动:

  • 通过索引直接设置项(如 arr[0] = newValue
  • 修改数组长度(如 arr.length = 0

解决方案是使用数组的变异方法(如 pushpop)或 Vue.set

性能优化建议

  • 避免频繁操作大型响应式对象。
  • 对于不需要响应式的数据,使用 Object.freeze 冻结。
  • 在 Vue 3.x 中,使用 shallowReactive 处理嵌套层级较浅的对象。

通过上述机制,Vue 实现了数据与视图的自动同步,开发者只需关注数据逻辑,无需手动操作 DOM。

标签: vue
分享给朋友:

相关文章

vue中如何实现循环

vue中如何实现循环

在 Vue 中实现循环 Vue 提供了 v-for 指令用于实现循环渲染列表数据。v-for 可以遍历数组、对象或数字范围,生成动态的 DOM 元素。 遍历数组 使用 v-for 遍历数组时,语法为…

vue实现bootstrap

vue实现bootstrap

Vue 中集成 Bootstrap 的方法 在 Vue 项目中集成 Bootstrap 可以通过以下方式实现,涵盖样式、组件和交互功能。 安装 Bootstrap 依赖 通过 npm 或 yarn…

vue实现翻译

vue实现翻译

Vue 实现翻译功能的方法 使用 i18n 插件实现多语言切换 安装 vue-i18n 插件: npm install vue-i18n 创建语言资源文件(如 en.json 和 zh.json):…

vue 分页 实现

vue 分页 实现

Vue 分页实现方法 使用第三方库(如 Element UI) Element UI 提供了现成的分页组件 el-pagination,适合快速集成。 安装 Element UI: npm ins…

vue实现gridlayout

vue实现gridlayout

Vue 实现 Grid Layout 使用 CSS Grid 布局 CSS Grid 是一种强大的布局系统,可以直接在 Vue 组件的样式中使用。通过定义网格容器和网格项,可以快速实现复杂的布局结构。…

vue实现div单选

vue实现div单选

Vue 实现 div 单选 在 Vue 中实现 div 单选可以通过 v-model 结合 v-for 和事件绑定来完成。以下是具体实现方法: 模板部分 <template> &l…