vue3的响应式设计原理

发布于:2025-05-11 ⋅ 阅读:(9) ⋅ 点赞:(0)

Vue 3 的响应式设计是其核心特性之一,依赖于 Proxy依赖收集机制,相比 Vue 2 的 Object.defineProperty,Vue 3 的响应式系统更加高效、灵活且易于维护。

以下是 Vue 3 响应式设计的核心原理:


一、核心机制概览

  1. 使用 Proxy 实现响应式

    • Vue 3 用 Proxy 包装对象,实现对属性的读取和设置的拦截(getset)。

    • 相比 Vue 2,Proxy 可以监听新增属性和删除属性,避免 Vue 2 的 Vue.set 限制。

  2. 依赖收集(Dep)与触发更新(Trigger)

    • Vue 会在 getter 中收集当前运行的副作用函数(例如组件的渲染函数)。

    • 当数据发生变化时,setter 会触发这些副作用函数,重新执行。

  3. 响应式核心工具函数

    • reactive():将对象转换为响应式对象。

    • ref():将基本类型(如 numberstring)或对象封装成响应式引用。

    • computed():计算属性,具备缓存能力。

    • effect()(Vue 内部 API):注册副作用函数,用于响应式依赖追踪。


二、基本流程图

  1. 调用 reactive(obj) -> 返回 Proxy 包装对象

  2. 首次访问属性 proxy.a -> 执行 get,收集依赖

  3. 修改属性 proxy.a = 2 -> 执行 set,触发依赖更新


三、依赖追踪与触发的简化示意

// 模拟一个简单响应式系统
let targetMap = new WeakMap();

function track(target, key) {
  const effect = activeEffect;
  if (!effect) return;

  let depsMap = targetMap.get(target);
  if (!depsMap) {
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }

  let deps = depsMap.get(key);
  if (!deps) {
    deps = new Set();
    depsMap.set(key, deps);
  }

  deps.add(effect);
}

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

  const deps = depsMap.get(key);
  deps && deps.forEach(effect => effect());
}

let activeEffect = null;
function effect(fn) {
  activeEffect = fn;
  fn(); // 执行函数,会触发 get,从而 track
  activeEffect = null;
}

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) {
      const result = Reflect.set(target, key, value, receiver);
      trigger(target, key);
      return result;
    }
  });
}

四、Vue 3 中响应式的优势

特性 Vue 2 Vue 3
基础实现 Object.defineProperty Proxy
新增/删除属性 需要手动使用 Vue.set 原生支持
性能 多层嵌套对象递归劫持,性能差 延迟代理,性能好
API 风格 Options API 为主 支持 Composition API

五、实战示例

import { reactive, effect } from 'vue'

const state = reactive({ count: 0 })

effect(() => {
  console.log(`count is: ${state.count}`)  // 自动收集依赖
})

state.count++ // 自动触发更新

如果你需要可视化原理图,我可以为你画一个响应式原理的流程图,要我帮你画一个吗?


网站公告

今日签到

点亮在社区的每一天
去签到