Heim > Artikel > Web-Frontend > Vue Learning spricht über die Prinzipien der Vorlagenkompilierung
Was ist eine Vorlagenkompilierung? Im folgenden Artikel geht es um die Vorlagenkompilierung in Vue und die Prinzipien der Vorlagenkompilierung. Ich hoffe, dass er für Sie hilfreich ist.
vue stellt eine Vorlagensyntax bereit, die es uns ermöglicht, die Bindungsbeziehung zwischen Status und DOM deklarativ zu beschreiben, wie zum Beispiel <p>{{name}}</p>
<p></p>
. <p>{{name}}</p>
<p></p>
。
模板编译指的是模板将编译成render函数的过程,渲染函数的作用是每次执行时,会根据最新状态生成新的vnode。
编译的过程是:模板作为输入 -> 模板编译 阶段->生成 渲染函数
解析器
:将模板解析为AST(Abstract Syntax Tree 抽象语法树)优化器
:遍历AST标记静态节点,因为静态节点不可变,不需要为打上标签的静态节点创建新的虚拟节点,直接克隆已有的虚拟节点。代码生成器
:使用AST生成渲染函数。将AST转换成代码字符串。将代码字符串放入渲染函数中,导出被外界使用。假设如下代码,有el
、template
、render
、$mount
//复杂案例 let vue = new Vue({ el: '#app', data() { return { a: 1, b: [1] } }, render(h) { return h('div', { id: 'hhh' }, 'hello') }, template: `<div id='hhh' style="aa:1;bb:2"><a>{{xxx}}{{ccc}}</a></div>` }).$mount('#app') console.log(vue) //脚手架创建的案例 let vue = new Vue({ render: h => h(App) }).$mount('#app')
1)渲染到哪个根节点上:判断有无el属性,有的话直接获取el根节点,没有的话调用$mount时去获取根节点
2)渲染哪个模板到根节点上去:是否调用render
函数传入了模板 render: h => h(App) -> <app></app>
解析器-将模板解析成AST
<div> <p>{{name}}</p> </div>
将上述模板解析成AST后,AST抽象语法树就是使用JS中的对象来描述一个节点,一个对象表示一个节点。
{ tag: "div" type: 1, //节点类型 staticRoot: false, static: false, plain: true, parent: undefined, //存放父节点 attrsList: [], attrsMap: {}, children: [ //存放孩子节点 { tag: "p" type: 1, staticRoot: false, static: false, plain: true, parent: {tag: "div", ...}, attrsList: [], attrsMap: {}, children: [{ type: 2, text: "{{name}}", static: false, expression: "_s(name)" }] } ] }
解析器的原理的是一小段一小段地截取模板字符串,每截取一小段字符串,就会根据截取出来的字符串类型触发不同的钩子函数,直到模板字符串截空停止。然后使用栈来确定层级关系
解析器内部分也分几个子解析器,如HTML解析器、文本解析器等。
HTML解析器的作用是解析HTML,在解析HTML的过程中不断触发各种钩子函数,
文本解析器是对HTML解析出来的文本进行二次加工,比如插值语法{{}}
如何确定DOM之间的层级关系?使用栈
在触发开始标签的钩子函数时,如果当前标签不是自闭合标签,就push
进stack
。
在触发结束标签的钩子函数时,就从栈中pop
Vorlage als Eingabe-> Vorlagenkompilierungsphase->Rendering-Funktion generieren
Interviewfragen
Parser: Analysieren Sie die Vorlage in AST (Abstract Syntax Tree)
Optimierer
: Durchlaufen Sie den AST, um statische Knoten zu markieren, da statische Knoten unveränderlich sind und dies nicht müssen Markieren Sie statische Knoten, um neue virtuelle Knoten zu erstellen und vorhandene virtuelle Knoten direkt zu klonen. Codegenerator
: Verwenden Sie AST, um Rendering-Funktionen zu generieren. Konvertieren Sie AST in eine Codezeichenfolge. Fügen Sie die Codezeichenfolge in die Rendering-Funktion ein und exportieren Sie sie zur Verwendung durch die Außenwelt. el code>, <code>template
, render
, $mount
🎜<div> <p>{{name}}</p> </div> //生成的render渲染函数 { render: `with(this){return _c('div',[_c('p',[_v(_s(name))])])}` } //格式化后 with(this){ return _c( 'div', [ _c( 'p', [ _v(_s(name)) ] ) ] ) }🎜🎜🎜🎜1) Auf welchen Stammknoten gerendert werden soll🎜: Bestimmen Sie, ob ein el-Attribut vorhanden ist, und wenn ja, rufen Sie es ab el direkt Root-Knoten, wenn nicht, erhalten Sie den Root-Knoten, wenn Sie $mount aufrufen🎜🎜🎜2) Welche Vorlage auf dem Root-Knoten gerendert werden soll🎜: Ob die
render
-Funktion aufgerufen und die Vorlage übergeben werden soll render: h => ; h(App) -> <app></app>
🎜{{}}
🎜🎜🎜Wie bestimmt man die hierarchische Beziehung zwischen DOMs? Stack verwenden 🎜push
stack
ein. pop
vom Stapel abgespielt🎜🎜🎜🎜🎜3. Optimierer – Statische Knoten im AST markieren🎜🎜🎜🎜Statisch markieren Teilbäume Die Vorteile🎜🎜优化器的内部实现主要分两步用递归的方式将所有节点添加 static 属性,true表示是静态的,false表示不是静态的。
静态根节点也是静态节点
如果一个静态根节点的子节点只有一个文本节点或没有子节点,那么不会标记成静态根节点,即使他们是,因为优化成本大于收益
怎么判断是否静态节点?
在将模板字符串解析成AST的时候,会根据不同的文本类型设置一个 type
type | 说明 | 是否时静态节点 |
---|---|---|
1 | 元素节点 | 进行一些排除 |
2 | 带遍历的动态文本节点 | 不是 |
3 | 不带遍历的纯文本节点 | 是 |
代码生成器的作用:将AST转化成渲染函数中的代码字符串
<div> <p>{{name}}</p> </div> //生成的render渲染函数 { render: `with(this){return _c('div',[_c('p',[_v(_s(name))])])}` } //格式化后 with(this){ return _c( 'div', [ _c( 'p', [ _v(_s(name)) ] ) ] ) }
生成代码字符串是一个递归的过程,从顶向下依次处理每一个AST节点。
节点有三种类型,分别对应三种不同的创建方法与别名。
类型 | 创建方法 | 别名 |
---|---|---|
元素节点 | createElement | _c |
文本节点 | createTextVNode | _v |
注释节点 | createEmptyVNode | _e |
渲染函数可以生成VNode的原因:渲染函数其实是执行了createElement,而createElement可以创建VNode。
代码字符串的拼接过程
递归AST来生成字符串,最先生成根节点,然后在子节点字符串生成后,将其拼接在根节点的参数中,子节点的子节点拼接在子节点的参数中,一层层拼接。
Das obige ist der detaillierte Inhalt vonVue Learning spricht über die Prinzipien der Vorlagenkompilierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!