跳到主要内容

认识

2023年06月10日
柏拉文
越努力,越幸运

一、认识


二、细节


<div>Hello {{ msg }}</div> 模版为例, 进行如下细节分析

2.1 解析

生成的 ast 如下

{
"children":[
{
"tag":"div",
"props":[

],
"children":[
{
"content":"Hello ",
"type":2
},
{
"type":5,
"content":{
"type":4,
"isStatic":false,
"content":"msg"
}
}
],
"type":1,
"tagType":0
}
],
"loc":{

},
"type":0
}

2.2 转换

转换后的 ast 如下

{
"children":[
{
"tag":"div",
"props":[

],
"children":[
{
"type":8,
"children":[
{
"content":"Hello ",
"type":2
},
" + ",
{
"type":5,
"content":{
"type":4,
"isStatic":false,
"content":"msg"
}
}
]
}
],
"type":1,
"tagType":0,
"codegenNode":{
"type":13,
"tag":"\"div\"",
"props":[

],
"children":[
{
"type":8,
"children":[
{
"content":"Hello ",
"type":2
},
" + ",
{
"type":5,
"content":{
"type":4,
"isStatic":false,
"content":"msg"
}
}
]
}
]
}
}
],
"loc":{

},
"type":0,
"codegenNode":{
"type":13,
"tag":"\"div\"",
"props":[

],
"children":[
{
"type":8,
"children":[
{
"content":"Hello ",
"type":2
},
" + ",
{
"type":5,
"content":{
"type":4,
"isStatic":false,
"content":"msg"
}
}
]
}
]
},
"helpers":[
null,
null
],
"components":[

],
"directives":[

],
"imports":[

],
"hoists":[

],
"temps":[

],
"cached":[

]
}

2.3 生成

生成的 render 函数如下:

(function anonymous(
) {
const _Vue = Vue

return function render(_ctx, _cache) {
with (_ctx) {
const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode } = _Vue


return _createElementVNode("div", [], ["Hello " + _toDisplayString(msg)])
}
}
})

如上所示: {{ }} 会生成一个 _toDisplayString(表达式) 的语句。

问题一、 msg 变量是哪里来的呢?

const _ctx = {
msg: "World"
}

function render(_ctx){
with(_ctx){
console.log("msg",msg)
}
}

问题二、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 渲染