在组件的渲染过程中,会安装(创建)一个渲染 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];
}
}
}