effect安装渲染

286 阅读1分钟

在组件的渲染过程中,会安装(创建)一个渲染 effect,即 Vue 3.0 在编译 template 的时候,对是否有订阅数据做出相应的判断,创建对应的渲染 effect,它的定义如下:

const setupRenderEffect = (instance, initialVNode, container, anchor, parentSuspense, isSVG) => {
    // create reactive effect for rendering
    instance.update = effect(function componentEffect() {
            ....
            instance.isMounted = true;
        }
        else {
            ...
        }
    }, (process.env.NODE_ENV !== 'production') ? createDevEffectOptions(instance) : prodEffectOptions);
};

我们来大致分析一下 setupRenderEffect()。它传入几个参数,它们分别为:

  • instance 当前 vm 实例
  • initialVNode 可以是组件 VNode 或者普通 VNode
  • container 挂载的模板,例如 div#app 对应的节点
  • anchor, parentSuspense, isSVG 普通情况下都为 null

effect函数定义如下

function effect(fn, options = EMPTY_OBJ) {
    // 判断手否已经安装渲染
    if (isEffect(fn)) {
        fn = fn.raw;
    }
    // 不是则创建响应式的effect
    const effect = createReactiveEffect(fn, options);
    // 数据是否懒加载
    if (!options.lazy) {
        effect();
    }
    return effect;
}

创建响应式的effect

function createReactiveEffect(fn, options) {
    const effect = function reactiveEffect(...args) {
        return run(effect, fn, args);
    };
    effect._isEffect = true;
    effect.active = true;
    effect.raw = fn;
    effect.deps = [];
    effect.options = options;
    return effect;
}

function run(effect, fn, args) {
    if (!effect.active) {
        return fn(...args);
    }
    if (!effectStack.includes(effect)) {
        cleanup(effect);
        try {
            enableTracking();
            effectStack.push(effect);
            activeEffect = effect;
            return fn(...args);
        }
        finally {
            effectStack.pop();
            resetTracking();
            activeEffect = effectStack[effectStack.length - 1];
        }
    }
}

参考链接:juejin.cn/post/684490…