Vue3响应式原理你还不会?

2023-11-08 16:39:21 浏览数 (1)

e4c8acf08dd6f7799b25970e411ed02c.jpege4c8acf08dd6f7799b25970e411ed02c.jpeg

Vue 3 的响应式系统是整个框架的核心,通过 Proxy 对象实现了数据和视图之间的双向绑定。下面我将详细分析 Vue 3 响应式系统的原理,包括代码示例和详细的解释。

1. 创建响应式数据对象:

首先,我们使用 reactive 函数来创建响应式数据对象。这个函数接受一个普通的 JavaScript 对象,并返回一个代理对象,该代理对象包含了数据对象的属性和拦截器,用于侦测属性的访问和修改。

代码语言:javascript复制
const state = reactive({
  count: 0
});

2. 代理对象的 get 拦截器(依赖追踪):

代理对象通过 Proxy 拦截器拦截对数据属性的访问。在 get 拦截器中,我们会进行依赖追踪,即收集当前激活的计算属性函数(effect)对属性的依赖。

代码语言:javascript复制
let activeEffect = null;

function effect(fn) {
  activeEffect = fn;
  fn(); // 执行计算属性函数
  activeEffect = null;
}

function track(target, key) {
  if (activeEffect) {
    // 收集依赖
    activeEffect.dependencies.push(key);
  }
}

const reactiveHandler = {
  get(target, key) {
    // 依赖追踪
    track(target, key);
    return target[key];
  }
};

const state = reactive({
  count: 0
});

3. 创建计算属性:

计算属性是基于响应式数据对象的派生属性,其值是通过计算函数获取的。在 Vue 3 中,可以使用 computed 函数来创建计算属性。

代码语言:javascript复制
function computed(getter) {
  let value;
  let dirty = true; // 初始标记为需要重新计算

  const effect = () => {
    if (dirty) {
      value = getter(); // 执行计算函数
      dirty = false;
    }
  };

  effect.dependencies = []; // 存储依赖属性

  effect(); // 初始执行计算属性函数

  return {
    effect,
    value,
  };
}

const double = computed(() => state.count * 2);

4. 计算属性的依赖收集:

在计算属性的 getter 函数中,依赖属性的访问会触发代理对象的 get 拦截器,进而触发依赖追踪。

代码语言:javascript复制
const double = computed(() => state.count * 2);
// 此时触发依赖追踪,将 state.count 加入 double 的依赖列表

5. 触发计算属性的重新计算:

当依赖属性发生变化时,触发计算属性的重新计算。这是通过触发函数(trigger)来实现的。

代码语言:javascript复制
function trigger(target, key) {
  // 找到依赖此属性的计算属性
  const effects = target[key].dependencies;
  if (effects) {
    effects.forEach(effect => {
      effect.dirty = true; // 标记为需要重新计算
    });
  }
}

const state = reactive({
  count: 0
});

const double = computed(() => state.count * 2);

console.log(double.value); // 输出 0

state.count = 2; // 数据变化,触发计算属性重新计算

console.log(double.value); // 输出 4,已经重新计算

6. 异步更新和调度器:

Vue 3 的响应式系统支持异步更新,以提高性能。它还引入了调度器(scheduler)的概念,可以控制计算属性和观察者何时执行。

代码语言:javascript复制
function computed(getter, options) {
  const runner = effect(getter, {
    lazy: true,
    ...options
  });

  const computed = {
    effect: runner,
    value: undefined
  };

  return computed;
}

调度器可以用来控制计算属性和观察者的执行时机,以减少计算的重复和提高性能。

这就是 Vue 3 响应式系统的基本原理,它通过 Proxy 对象和依赖追踪来实现数据和视图的双向绑定,以及计算属性和观察者来处理派生数据和副作用。这个系统使 Vue 3 更高效、更灵活,并能够更好地处理复杂的应用场景。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞