編譯流程:javascript
A[]
,B[]
。A
數組中,同時去除模板字符串中的匹配部分。children[]
)等信息,設置節點的父節點指向當前父節點(currentParent),將語法樹節點添加到添加到數組B
中,同時設置節點爲當前父節點。B
中的節點(數組中的最後一個節點),並從數組B
中移除,同時設置數組的最後一個節點爲當前父節點,將找到的節點添加到當前父節點的子節點數組children[]
中。A
中和結束標籤名稱相同的起始標籤,並從數組A
中移除。經過數組A
能夠匹配開始標籤對應的結束標籤。經過數組B
構建層級結構,造成語法樹。構建過程是一個深度遍歷。對數組
A
、B
的操做和棧一致。java根節點指向第一個添加到數組
B
的節點,最後返回根節點。node
遍歷語法樹,標記語法樹中的靜態節點。根據以前的標記結果,再遍歷標記靜態根節點。在渲染時,對有標記靜態根節點的子樹進行緩存,下次渲染時直接從緩存中讀取。express
知足如下一個條件且子節點也都是靜態節點:數組
function isStatic (node) { if (node.type === 2) { // expression return false } if (node.type === 3) { // text return true } return !!(node.pre || ( !node.hasBindings && // no dynamic bindings !node.if && !node.for && // not v-if or v-for or v-else !isBuiltInTag(node.tag) && // not a built-in 不是內建組件slot,component isPlatformReservedTag(node.tag) && // not a component 是原生標籤 !isDirectChildOfTemplateFor(node) &&// 不是有for指令的template標籤的子標籤 Object.keys(node).every(isStaticKey)// 節點上的每一個屬性都是靜態屬性 )) }
節點自己是靜態節點,而且包含子節點,若是隻有一個子節點,該子節點不能是純文本節點(若是不知足這些條件作優化,成本將會超過它帶來的價值)。緩存
// For a node to qualify as a static root, it should have children that // are not just static text. Otherwise the cost of hoisting out will // outweigh the benefits and it's better off to just always render it fresh. if (node.static && node.children.length && !( node.children.length === 1 &&// 1.靜態節點(子節點都是靜態節點),2. 包含子節點,3. 但又不是隻有一個文本子節點 node.children[0].type === 3 )) { node.staticRoot = true; return } else { node.staticRoot = false; }
遍歷語法樹,根據每一個節點生成表達式字符串,而後拼接或者嵌套這些字符串,最後造成一個和語法樹對應的完整的表達式字符串,渲染時經過with執行字符串中的表達式,生成虛擬節點樹。優化
function generate ( ast, options ) { var state = new CodegenState(options); var code = ast ? genElement(ast, state) : '_c("div")';// 完整的表達式字符串 return { render: ("with(this){return " + code + "}"), staticRenderFns: state.staticRenderFns// 保存了靜態根節點子樹生成的表達式字符串 } }
在遍歷過程當中,將有標記靜態根節點的子樹生成的表達式字符串保存到單獨的數組中,完整的表達式字符串保存了靜態子樹表達式字符串在數組中的索引。ui
function genStatic (el, state) { el.staticProcessed = true; var originalPreState = state.pre; if (el.pre) { state.pre = el.pre; } state.staticRenderFns.push(("with(this){return " + (genElement(el, state)) + "}")); state.pre = originalPreState; return ("_m(" + (state.staticRenderFns.length - 1) + (el.staticInFor ? ',true' : '') + ")")// 保存靜態子樹表達式字符串在數組中的索引 }