认识
2024年03月13日
一、认识
二、细节
2.1 解析
<h1 v-if="isShow">你好,世界</h1>
解析成如下的 AST
{
type: "1",
ns: 0,
tag: h1,
tagType:0,
props: [
{
type: 7,
name: 'if',
exp: {
type: 4,
content: "isShow",
isStatic: false,
constType: 0
}
}
]
}
2.2 转换
转换生成的 JavaScript AST
如下:
{
type: 9,
branches: [
{
type: 10,
condition: {
type: 4,
content: "isShow",
isStatic: false,
loc: {}
},
children: [
{
type: 1,
tag: h1,
tagType: 0,
children: [
{
type: 2,
content: "你好,世界"
}
],
codegenNode: {
type: 13,
tag: "h1",
children: [
{
type: 2,
content: "你好,世界"
}
]
}
}
]
}
]
}
2.3 生成
生成的渲染函数如下所示:
(function anonymous(
) {
const _Vue = Vue
return function render(_ctx, _cache) {
with (_ctx) {
const { createElementVNode: _createElementVNode, createCommentVNode: _createCommentVNode } = _Vue
return _createElementVNode("div", [], [isShow ?_createElementVNode("h1", null, ["你好,世界"]) : _createCommentVNode("v-if", true)])
}
}
})
因此, v-if
节点的处理结果是一个三元表达式
问题一、 isShow
变量是哪里来的呢?
const _ctx = {
isShow: true
}
function render(_ctx){
with(_ctx){
console.log("isShow",isShow)
}
}
问题二、render
在哪里调用的呢?
export function renderComponentRoot(instance) {
const { type, vnode, render, data = {} } = instance;
let result;
try {
if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
result = normalizeVNode(render.call(data, data));
}
} catch (error) {
console.log(error);
}
return result;
}
由上可知, render
函数的 this
指向为 data
, render(_ctx)
中的 _ctx
也为 data
。
2.4 渲染
三、问题
3.1 Vue.js 3.0 v-if 与 v-for 的优先级?
Vue.js 3.0
中, 在同一元素上使用 v-if
和 v-for
时, v-if
比 v-for
的优先级更高(源码中 v-if
指令优先被处理), 这意味着 v-if
的条件将无法访问到 v-for
作用域内定义的变量别名。正确的做法是通过 computed
筛选需要渲染的元素 或者通过将 v-for
和 v-if
分开使用即可。