当前位置:首页 > VUE

vue响应式的实现

2026-01-23 15:53:01VUE

Vue 响应式实现原理

Vue 的响应式系统基于 数据劫持依赖收集 实现,核心是通过 Object.defineProperty(Vue 2)或 Proxy(Vue 3)监听数据变化,触发视图更新。

Vue 2 的实现方式

数据劫持
通过 Object.defineProperty 重写对象的属性访问器(getter/setter),在数据读取和修改时拦截操作:

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log(`读取 ${key}: ${val}`);
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        console.log(`设置 ${key}: ${newVal}`);
        val = newVal;
      }
    }
  });
}

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

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;
}

数组处理
重写数组的变异方法(如 pushpop),在调用时手动触发更新:

const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift'].forEach(method => {
  const original = arrayProto[method];
  arrayMethods[method] = function(...args) {
    const result = original.apply(this, args);
    dep.notify(); // 触发更新
    return result;
  };
});

Vue 3 的实现方式

Proxy 代理
使用 Proxy 直接监听整个对象,避免 Vue 2 中递归遍历和数组 hack 的问题:

function reactive(obj) {
  return new Proxy(obj, {
    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;
    }
  });
}

Effect 与依赖追踪
通过 effect 函数和 WeakMap 结构管理依赖关系:

const targetMap = new WeakMap();
function track(target, key) {
  if (!activeEffect) return;
  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;
  const effects = depsMap.get(key);
  effects && effects.forEach(effect => effect());
}

性能优化对比

  1. Vue 2 的局限性

    • 需要递归遍历对象的所有属性初始化响应式。
    • 无法检测新增/删除属性(需使用 Vue.set/Vue.delete)。
    • 数组需通过重写方法实现响应式。
  2. Vue 3 的优势

    • Proxy 直接代理整个对象,无需递归初始化。
    • 支持动态新增/删除属性。
    • 性能更高,内存占用更少。

实践示例

Vue 2 响应式数据

const vm = new Vue({
  data: { count: 0 },
  template: `<div>{{ count }}</div>`
});
vm.count++; // 视图自动更新

Vue 3 Composition API

vue响应式的实现

import { ref, effect } from 'vue';
const count = ref(0);
effect(() => {
  console.log(`Count is: ${count.value}`);
});
count.value++; // 触发 effect

标签: vue
分享给朋友:

相关文章

vue登录业务的实现

vue登录业务的实现

实现登录业务的基本流程 在Vue中实现登录业务通常涉及前端界面设计、表单验证、API请求交互、状态管理以及路由控制等环节。以下是核心实现步骤: 登录表单设计与验证 创建包含用户名和密码输入框的登录组…

vue 实现豆瓣

vue 实现豆瓣

以下是基于 Vue 实现豆瓣电影类功能的实现方案,涵盖核心模块和技术要点: 数据获取与 API 调用 使用豆瓣开放 API(需注意调用频率限制)或第三方代理接口 推荐 axios 进行异步请求,配合…

实现vue cli

实现vue cli

安装 Vue CLI 确保系统中已安装 Node.js(版本建议 12.x 或更高)。通过 npm 全局安装 Vue CLI: npm install -g @vue/cli 安装完成后验证版本:…

vue 简单实现

vue 简单实现

以下是 Vue 的简单实现示例,涵盖基础模板、数据绑定、方法及生命周期: 基础模板与数据绑定 <div id="app"> <p>{{ message }}</…

vue 实现循环

vue 实现循环

Vue 实现循环的方法 在 Vue 中,可以使用 v-for 指令来实现循环渲染列表数据。以下是几种常见的循环实现方式: 基本数组循环 <template> <ul>…

vue 实现vshow

vue 实现vshow

Vue 实现 v-show 在 Vue 中,v-show 是一个常用的指令,用于根据条件控制元素的显示或隐藏。与 v-if 不同,v-show 不会移除 DOM 元素,而是通过 CSS 的 displ…