上兩文章vue
淺析Vue源碼(四)—— $mount中template的編譯--parsenode
淺析Vue源碼(五)—— $mount中template的編譯--optimizegit
parse,optimize函數的功能,這裏,咱們主要介紹generate。github
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。bash
要是喜歡就給我一個star,github函數
感謝muwoo提供的思路。post