静态提升
下面的静态节点会被提升
- 元素节点
- 没有绑定动态内容
// vue2 的静态节点
render(){
createVNode("h1", null, "Hello World")
// ...
}
// vue3 的静态节点
const hoisted = createVNode("h1", null, "Hello World")
function render(){
// 直接使用 hoisted 即可
}
静态属性会被提升
<div class="user">
{{user.name}}
</div>
const hoisted = { class: "user" }
function render(){
createVNode("div", hoisted, user.name)
// ...
}
预字符串化
<div class="menu-bar-container">
<div class="logo">
<h1>logo</h1>
</div>
<ul class="nav">
<li><a href="">menu</a></li>
<li><a href="">menu</a></li>
<li><a href="">menu</a></li>
<li><a href="">menu</a></li>
<li><a href="">menu</a></li>
</ul>
<div class="user">
<span>{{ user.name }}</span>
</div>
</div>
当编译器遇到大量连续的静态内容,会直接将其编译为一个普通字符串节点
const _hoisted_2 = _createStaticVNode("<div class=\"logo\"><h1>logo</h1></div><ul class=\"nav\"><li><a href=\"\">menu</a></li><li><a href=\"\">menu</a></li><li><a href=\"\">menu</a></li><li><a href=\"\">menu</a></li><li><a href=\"\">menu</a></li></ul>")
vue2虚拟节点树
vue3虚拟节点树
缓存事件处理函数
<button @click="count++">plus</button>
// vue2
render(ctx){
return createVNode("button", {
onClick: function($event){
ctx.count++;
}
})
}
// vue3
render(ctx, _cache){
return createVNode("button", {
onClick: cache[0] || (cache[0] = ($event) => (ctx.count++))
})
}
Block Tree
vue2在对比新旧树的时候,并不知道哪些节点是静态的,哪些是动态的,因此只能一层一层比较,这就浪费了大部分时间在比对静态节点上
<form>
<div>
<label>账号:</label>
<input v-model="user.loginId" />
</div>
<div>
<label>密码:</label>
<input v-model="user.loginPwd" />
</div>
</form>
vue3依靠强大的编译器,给每一个节点标记是静态节点还是动态节点,并且会把所有的动态节点提取到根节点(Block节点,保存为一个数组,每一项是一个节点),在对比新旧树的时候不需要对整个树进行遍历,直接对比Block节点中保存的动态节点数组
PatchFlag
vue2在对比每一个节点时,并不知道这个节点哪些相关信息会发生变化,因此只能将所有信息依次比对
<div class="user" data-id="1" title="user name">
{{user.name}}
</div>
vue3依靠强大的编译器,给每个动态节点的相关动态信息做一个标记,对比时仅对比相关动态信息