认识
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
。