视图渲染
组件渲染
渲染管线:https://cn.vuejs.org/guide/extras/rendering-mechanism.html#render-pipeline
- 模板编译
- mount。首次挂载
- update。更新
- pre。比如 watch、watchEffect
- flushing。queueJob
- post。比如 onMounted
批处理是怎么实现的?
每个 effect 会有一个 id 标识,相同 id 的 effect 会合并
生命周期
参考
模板编译
h --> createVNode --> 真实 DOM
现在有这样一个模板
<div id="app">
<p>{{name}}</p>
<p>{{age}}</p>
</div>
vue 会基于 AST 将其编译成 render
函数,该函数会返回一个虚拟 DOM 对象
function render() {
with (this) {
return _c(
"div",
{
attrs: {
id: "app",
},
},
[_c("p", [_v(_s(name))]), _c("p", [_v(_s(age))])]
);
}
}
slot 插槽
<div>
<slot name="header"></slot>
</div>
编译生成 render 函数如下:
import {
renderSlot as _renderSlot,
openBlock as _openBlock,
createElementBlock as _createElementBlock,
} from "vue";
export function render(_ctx) {
return (
_openBlock(),
_createElementBlock("div", null, [_renderSlot(_ctx.$slots, "header")])
);
}
nextTick
加入微任务队列
export function nextTick<T = void>(
this: T,
fn?: (this: T) => void
): Promise<void> {
const p = currentFlushPromise || resolvedPromise;
return fn ? p.then(this ? fn.bind(this) : fn) : p;
}
使用 nextTick 需要放在修改响应式数据之后,就是为了让 nextTick 的回调添加到微任务队列时,排在 flusobs 方法之后,保证能够在 nextTick 回调中拿到最新的 dom
参考
内置组件【WIP】
KeepAlive
参考 https://juejin.cn/post/7069422231387439111
- 隐藏 DOM 节点,缓存实例(但是仍然会比较 props 的变化)
- LRU 策略