上兩文章
淺析Vue原始碼(四)—— $mount中template的編譯--parse
淺析Vue原始碼(五)—— $mount中template的編譯--optimize
parse,optimize函式的功能,這裡,我們主要介紹generate。
generate 函式主要功能就是根據 AST 結構拼接生成 render function 的字串。
export function generate (
ast: ASTElement | void,
options: CompilerOptions
): CodegenResult {
const state = new CodegenState(options)
const code = ast ? genElement(ast, state) : '_c("div")'
return {
// 最外層包一個 with(this) 之後返回
render: `with(this){return ${code}}`,
// 這個陣列中的函式與 VDOM 中的 diff 演算法優化相關
// 我們會在編譯階段給後面不會發生變化的 VNode 節點打上 staticRoot 為 true 的標
// 那些被標記為 staticRoot 節點的 VNode 就會單獨生成 staticRenderFns
staticRenderFns: state.staticRenderFns
}
}
複製程式碼
其中 genElement 函式是什麼呢?--是會根據 AST 的屬性呼叫不同的方法生成字串返回。也就是拼接字串了:
export function genElement (el: ASTElement, state: CodegenState): string {
if (el.staticRoot && !el.staticProcessed) {
return genStatic(el, state)
} else if (el.once && !el.onceProcessed) {
return genOnce(el, state)
} else if (el.for && !el.forProcessed) {
return genFor(el, state)
} else if (el.if && !el.ifProcessed) {
return genIf(el, state)
} else if (el.tag === 'template' && !el.slotTarget) {
return genChildren(el, state) || 'void 0'
} else if (el.tag === 'slot') {
return genSlot(el, state)
} else {
// component or element
let code
if (el.component) {
code = genComponent(el.component, el, state)
} else {
const data = el.plain ? undefined : genData(el, state)
const children = el.inlineTemplate ? null : genChildren(el, state, true)
code = `_c('${el.tag}'${
data ? `,${data}` : '' // data
}${
children ? `,${children}` : '' // children
})`
}
// module transforms
for (let i = 0; i < state.transforms.length; i++) {
code = state.transforms[i](el, code)
}
return code
}
}
複製程式碼
以上就是 compile 函式中三個核心步驟的介紹,compile 之後我們得到了 render function 的字串形式,後面通過 new Function 得到真正的渲染函式。DOM 初始化過程最後一步是根據渲染函式生成 Vnode,根據此 Vnode 生成真實 DOM,插入 DOM 樹中,並將該 Vnode 記錄為 preVnode。
要是喜歡就給我一個star,github
感謝muwoo提供的思路。