当前位置:首页 > VUE

vue如何实现响应式

2026-02-23 09:16:17VUE

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}`);
      return val;
    },
    set(newVal) {
      console.log(`修改 ${key} 为 ${newVal}`);
      val = newVal;
    }
  });
}

在 Vue 3 中,改用 Proxy 实现数据劫持,可以监听整个对象而无需递归遍历属性。

vue如何实现响应式

const reactive = (target) => {
  return new Proxy(target, {
    get(target, key) {
      console.log(`访问 ${key}`);
      return target[key];
    },
    set(target, key, value) {
      console.log(`修改 ${key} 为 ${value}`);
      target[key] = value;
      return true;
    }
  });
};

依赖收集

Vue 通过依赖收集跟踪数据的依赖关系。每个响应式属性都有一个对应的 Dep 实例,用于存储依赖(Watcher)。当数据被访问时,当前 Watcher 会被添加到 Dep 中;当数据被修改时,Dep 会通知所有 Watcher 更新。

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

实现 Watcher

Watcher 是数据和视图之间的桥梁,负责在数据变化时更新视图。

vue如何实现响应式

let target = null;

class Watcher {
  constructor(vm, exp, fn) {
    this.vm = vm;
    this.exp = exp;
    this.fn = fn;
    target = this;
    this.vm[this.exp]; // 触发 getter 收集依赖
    target = null;
  }
  update() {
    this.fn.call(this.vm, this.vm[this.exp]);
  }
}

响应式数据示例

结合以上概念,可以创建一个简单的响应式系统:

function observe(data) {
  Object.keys(data).forEach(key => {
    let value = data[key];
    const dep = new Dep();

    Object.defineProperty(data, key, {
      get() {
        dep.depend();
        return value;
      },
      set(newVal) {
        if (newVal === value) return;
        value = newVal;
        dep.notify();
      }
    });
  });
}

const vm = { count: 0 };
observe(vm);

new Watcher(vm, 'count', (val) => {
  console.log(`count 更新为 ${val}`);
});

vm.count++; // 输出 "count 更新为 1"

数组响应式处理

Vue 对数组方法(如 pushpop)进行了特殊处理,通过重写这些方法实现响应式。

const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);

['push', 'pop', 'shift', 'unshift'].forEach(method => {
  const original = arrayProto[method];
  arrayMethods[method] = function(...args) {
    const result = original.apply(this, args);
    this.__ob__.dep.notify(); // 通知更新
    return result;
  };
});

Vue 3 的改进

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

  • 无需递归遍历对象属性。
  • 可以监听新增或删除的属性。
  • 对数组的支持更自然,无需重写方法。
const reactive = (target) => {
  const handler = {
    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;
    }
  };
  return new Proxy(target, handler);
};

总结

Vue 的响应式系统通过数据劫持和依赖收集实现数据的自动更新。Vue 2 使用 Object.defineProperty,Vue 3 改用 Proxy,提高了性能和灵活性。理解这些原理有助于更好地使用 Vue 并解决相关问题。

标签: 如何实现vue
分享给朋友:

相关文章

vue实现分类

vue实现分类

Vue实现分类功能的方法 使用v-for和计算属性 通过计算属性对数据进行分类处理,结合v-for渲染分类后的列表。示例代码: <template> <div>…

vue的实现

vue的实现

Vue 的实现原理 Vue 是一个渐进式 JavaScript 框架,其核心实现主要包括响应式系统、虚拟 DOM、模板编译和组件化机制。以下是 Vue 实现的主要技术细节。 响应式系统 Vue 的响…

vue滚动实现

vue滚动实现

Vue 滚动实现方法 使用原生滚动 在 Vue 中可以通过 ref 获取 DOM 元素,调用原生滚动方法实现滚动效果。适用于简单场景。 <template> <div ref=…

vue实现布局

vue实现布局

Vue 实现布局方法 Vue 提供了多种方式实现页面布局,可以通过组件化、CSS 框架或自定义样式完成。以下是几种常见方法: 使用 CSS Flexbox 或 Grid 通过 Vue 单文件组件结合…

vue 实现modal

vue 实现modal

Vue 实现 Modal 的方法 使用 Vue 原生组件 通过 Vue 的组件系统可以轻松实现 Modal。创建一个可复用的 Modal 组件,通过 props 控制显示与隐藏。 <temp…

vue 绑定实现

vue 绑定实现

Vue 绑定实现 Vue 提供了多种数据绑定的方式,包括文本插值、属性绑定、事件绑定、双向绑定等。以下是常见的绑定实现方法: 文本插值 使用双大括号 {{ }} 进行文本插值,将数据动态渲染到 D…