淺析Vue原始碼(六)—— $mount中template的編譯–generate

DIVI發表於2018-10-05

上兩文章

淺析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提供的思路。

來源:https://juejin.im/post/5bb718bbf265da0ac8494a7b

相關文章