模板字符串编译成语法树编译过程:编译过程中涉及到两个数组A[]、B[]。解析模板字符串。当匹配到起始标签时,将包含起始标签信息(name、attribute)的对象添加到A数组中,将模板字符串中匹配的部分去掉。根据起始标签信息创建语法树节点。语法树节点包含名称、属性、父节点、子节点(children[])等信息。设置节点的父节点指向当前父节点(currentParent),将语法树节点添加到数组B中,设置节点为当前父节点。继续解析模板字符串,如果匹配到开始标签,则继续执行步骤2。如果匹配到结束标签,则找到刚刚添加到数组B中的节点(数组的最后一个节点),将其从数组B中移除,并将数组的最后一个节点设置为当前父节点,将找到的节点添加到当前父节点的子节点的数组children[]中。找到数组A中最近加入的与结束标签同名的开始标签,将其从数组A中移除。开始标签对应的结束标签可以通过数组A进行匹配。通过数组构建层次结构B形成语法树。构建过程是一个深度遍历。对数组A和B的操作和栈是一致的。根节点指向第一个加入数组B的节点,最后返回根节点。语法树优化:静态节点标记遍历语法树,标记语法树中的静态节点。根据之前的标记结果,遍历标记的静态根节点。渲染时,将静态根节点标记的子树缓存起来,下次渲染时直接从缓存中读取。如何判断静态节点满足以下条件之一且其子节点也是静态节点:具有pre属性的文本节点没有表达式;它不是内置组件节点;没有动态绑定;没有if或for,也没有for指令节点的子节点;节点上的属性都是静态属性。functionisStatic(node){if(node.type===2){//表达式返回false}if(node.type===3){//文本返回true}return!!(node.pre||(!node.hasBindings&&//没有动态绑定!node.if&&!node.for&&//不是v-if或v-for或v-else!isBuiltInTag(node.tag)&&//不是内置Built-incomponentslot,componentisPlatformReservedTag(node.tag)&&//notacomponentisanativetag!isDirectChildOfTemplateFor(node)&&//isnotasubtagofatemplatetagwithafor指令Object.keys(node).every(isStaticKey)//节点上的每个属性都是静态属性))}如何判断静态根节点本身是静态节点,包含子节点。如果只有一个子节点,则该子节点不可能是明文节点(如果不满足优化这些条件,代价会超过它带来的价值)。//要使节点符合静态根的条件,它应该有//不只是静态文本的子节点。否则,提升的成本将//超过收益,最好始终将其呈现为新鲜。if(node.static&&node.children.length&&!(node.children.length===1&&//1.静态节点(子节点都是静态节点),2.包含子节点,3.但不只有一个Text子节点node.children[0].type===3)){node.staticRoot=true;返回}else{node.staticRoot=false;}将语法树转化为表达式串,并根据每个节点遍历语法树生成表达式串,然后将这些串串接或嵌套,形成语法树对应的完整表达式串。渲染时,通过with执行字符串中的表达式,生成虚拟节点树。函数生成(ast,选项){varstate=newCodegenState(选项);var代码=ast?genElement(ast,state):'_c("div")';//完整的表达式字符串return{render:("with(this){return"+code+"}"),staticRenderFns:state.staticRenderFns//保存静态根节点的子树生成的表达式字符串}}在遍历过程中,会有一个标记为静态根节点的子树生成的表达式字符串存储在一个单独的数组中,完整的表达式字符串存储索引数组中的静态子树表达式字符串。函数genStatic(el,state){el.staticProcessed=true;varoriginalPreState=state.pre;如果(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':'')+")")//存放静态子树表达式字符串在数组中的索引}
