vue3的effect函数作用

822 阅读3分钟

在 Vue 3 的响应式系统中,effect 函数是核心机制之一,它的作用是创建一个响应式副作用(Reactive Effect),能够自动追踪依赖的响应式数据,并在这些数据变化时重新执行对应的副作用逻辑。它是 Vue 3 实现数据驱动视图更新的底层基础。


一、effect 的核心作用

  1. 依赖追踪(Dependency Tracking)
    当你在 effect 中访问响应式对象(如 refreactive)时,Vue 会自动记录这些依赖关系。
    例如

    import { effect, reactive } from 'vue';
    
    const state = reactive({ count: 0 });
    
    effect(() => {
      console.log('Count changed:', state.count); // 自动追踪 state.count 的依赖
    });
    
  2. 响应式触发(Reactive Trigger)
    当依赖的响应式数据发生变化时,effect 会自动重新执行其回调函数:

    state.count++; // 触发 effect 重新执行,输出 "Count changed: 1"
    

二、effect 的应用场景

1. 组件渲染(Component Rendering)

Vue 组件的渲染函数本质上被包裹在一个 effect 中。当组件依赖的响应式数据变化时,effect 会触发重新渲染:

// 伪代码示例
const componentUpdateEffect = effect(() => {
  renderComponent(); // 渲染逻辑
});

2. 计算属性(Computed Properties)

计算属性的实现基于 effect,通过缓存结果并在依赖变化时重新计算:

const count = ref(0);
const doubled = computed(() => count.value * 2);
// computed 内部通过 effect 追踪 count.value 的变化

3. 侦听器(Watch API)

watchwatchEffect 底层依赖 effect 实现依赖追踪和回调触发:

watchEffect(() => {
  console.log('WatchEffect triggered:', state.count);
});

4. 自定义响应式逻辑

开发者可以直接使用 effect 实现高级响应式逻辑:

// 当窗口大小变化时,自动更新响应式数据
const windowSize = reactive({ width: 0, height: 0 });

effect(() => {
  const updateSize = () => {
    windowSize.width = window.innerWidth;
    windowSize.height = window.innerHeight;
  };
  window.addEventListener('resize', updateSize);
  // 清理副作用(重要!)
  return () => window.removeEventListener('resize', updateSize);
});

三、effect 的关键特性

特性说明
自动依赖追踪只有在回调中实际使用的响应式属性会被追踪为依赖。
异步调度默认情况下,副作用会在响应式数据变化后异步执行(避免重复触发)。
清理机制可通过返回一个函数清理副作用(如取消事件监听)。
手动控制可通过 stop 方法停止响应式副作用的执行。

四、使用示例

1. 基本用法

import { effect, ref } from 'vue';

const count = ref(0);

// 创建 effect
const stop = effect(() => {
  console.log('Current count:', count.value);
});

count.value = 1; // 输出 "Current count: 1"

// 手动停止 effect
stop();
count.value = 2; // 不再触发输出

2. 清理副作用

effect((onCleanup) => {
  const timer = setInterval(() => {
    console.log('Running...');
  }, 1000);

  onCleanup(() => {
    clearInterval(timer); // 清理定时器
  });
});

五、注意事项

  1. 避免无限循环
    effect 中修改依赖的响应式数据可能导致无限循环:

    effect(() => {
      state.count++; // 错误:每次执行都会触发自身重新执行!
    });
    
  2. 性能优化
    对于高频更新的数据(如滚动事件),可使用 effectScope 或手动控制触发频率。

  3. 与 React 的对比
    Vue 的 effect 类似于 React 的 useEffect,但依赖追踪是自动的,无需显式声明依赖数组。


六、底层原理

Vue 3 的响应式系统通过 Proxy 拦截对象的读写操作,结合 effect 的依赖追踪和触发机制,实现了高效的数据驱动更新。当一个 effect 执行时:

  1. 触发响应式数据的 get 操作,将当前 effect 注册为依赖。
  2. 响应式数据变化时,触发 set 操作,通知所有关联的 effect 重新执行。

总结

effect 是 Vue 3 响应式系统的核心,用于建立数据与副作用之间的动态绑定。理解它的机制,能帮助你更好地使用 Vue 的高级功能(如自定义响应式逻辑),或在需要时直接操作底层 API。