


Pembelajaran sudut: analisis ringkas DOM tambahan dalam pengkompil Ivy
Artikel ini adalah tentang mempelajari rangka kerja Angular dan membawa anda melalui DOM tambahan dalam pengkompil Ivy, saya harap ia akan membantu anda!
Sebagai rangka kerja hadapan yang direka "untuk projek bahagian hadapan berskala besar", Angular sebenarnya mempunyai banyak reka bentuk yang patut dirujuk dan dipelajari reka bentuk dan fungsi ini prinsip. Artikel ini memfokuskan pada pengkompil Ivy, fungsi teras Angular, dan memperkenalkan reka bentuk DOM tambahannya. [Tutorial berkaitan yang disyorkan: "tutorial sudut"]
Apabila memperkenalkan rangka kerja bahagian hadapan, saya sering memperkenalkan enjin templat. Untuk proses pemaparan enjin templat, rangka kerja seperti Vue/React menggunakan reka bentuk seperti DOM maya.
Dalam pengkompil Angular Ivy, DOM maya tidak digunakan, tetapi DOM tambahan digunakan.
DOM Inkremental
Dalam pengkompil Ivy, produk yang disusun templat adalah berbeza daripada Enjin Lihat Ini adalah untuk menyokong keupayaan seperti kompilasi berasingan dan kompilasi tambahan.
Sebagai contoh, <span>My name is {{name}}</span>
kod templat ini, kod yang disusun dalam pengkompil Ivy mungkin akan kelihatan seperti ini:
// create mode if (rf & RenderFlags.Create) { elementStart(0, "span"); text(1); elementEnd(); } // update mode if (rf & RenderFlags.Update) { textBinding(1, interpolation1("My name is", ctx.name)); }
Seperti yang anda lihat, berbanding kod dalam View Engine elementDef(0,null,null,1,'span',...),
, elementStart()
dan elementEnd()
adalah API yang lebih menyegarkan Mereka menggunakan reka bentuk DOM tambahan.
DOM Bertambah lwn DOM Maya
DOM maya mesti telah difahami oleh semua orang Proses pengiraan terasnya termasuk:
Gunakan objek JavaScript Simulasikan DOM. pokok dan dapatkan pokok DOM maya.
Apabila data halaman berubah, pepohon DOM maya baharu dijana dan perbezaan antara pepohon DOM maya lama dan baharu dibandingkan.
Gunakan perbezaan pada pokok DOM sebenar.
Walaupun DOM maya menyelesaikan masalah prestasi yang disebabkan oleh kemas kini halaman dan pemaparan yang kerap, DOM maya tradisional masih mempunyai kesesakan prestasi berikut:
- Dalam satu The keseluruhan pepohon DOM maya komponen masih perlu dilalui di dalam komponen
- Dalam kes di mana sesetengah komponen hanya mempunyai sebilangan kecil nod dinamik dalam keseluruhan templat, traversal ini adalah satu pembaziran prestasi
- Logik rekursif dan kemas kini Mudah menyebabkan pemaparan UI disekat dan pengalaman pengguna direndahkan
Sebagai tindak balas kepada situasi ini, rangka kerja seperti React dan Vue juga telah membuat lebih banyak pengoptimuman Sebagai contoh, React telah melaksanakan algoritma untuk perbezaan pokok, perbezaan komponen dan perbezaan elemen, sambil memperkenalkan penjadualan tugas untuk mengawal pengiraan dan pemaparan kemas kini keadaan. Dalam Vue 3.0, kemas kini DOM maya dilaraskan daripada skop keseluruhan sebelumnya kepada skop pokok Struktur pepohon akan membawa kepada penyederhanaan algoritma dan peningkatan prestasi.
Dalam apa jua keadaan, terdapat masalah yang tidak dapat dielakkan dalam reka bentuk DOM maya: setiap operasi pemaparan memperuntukkan pepohon DOM maya baharu, yang sekurang-kurangnya cukup besar untuk menampung nod yang diubah, dan biasanya lebih besar Beberapa, reka bentuk sedemikian akan menghasilkan lebih banyak penggunaan memori. Apabila pokok DOM maya yang besar memerlukan kemas kini yang berat, terutamanya pada peranti mudah alih yang dikekang memori, prestasi boleh terjejas.
Idea reka bentuk teras DOM tambahan ialah:
Apabila mencipta pokok DOM (maya) baharu, berjalan di sepanjang pokok sedia ada dan semasa anda pergi Cari perubahan.
Jika tiada perubahan, jangan peruntukkan memori
Jika ada, tukar pokok sedia ada (peruntukkan memori hanya apabila benar-benar perlu; ) dan Gunakan perbezaan pada DOM fizikal.
(maya) diletakkan dalam kurungan di sini kerana apabila mencampurkan maklumat meta pra-pengiraan ke dalam nod DOM sedia ada, pokok DOM fizikal digunakan dan bukannya bergantung pada pokok DOM maya Ia sebenarnya cukup pantas.
DOM Inkremental mempunyai dua kelebihan utama berbanding pendekatan berasaskan DOM maya:
- Ciri tambahan membolehkan pengurangan ketara dalam peruntukan memori semasa proses pemaparan, menghasilkan prestasi Ramalan yang lebih cekap
- Ia memetakan dengan mudah kepada kaedah berasaskan templat. Pernyataan kawalan dan gelung boleh dicampur secara bebas dengan pengisytiharan elemen dan atribut
Reka bentuk DOM tambahan telah dicadangkan oleh Google dan ia juga menyediakan perpustakaan sumber terbuka google/incremental-dom, Ia adalah perpustakaan untuk menyatakan dan menggunakan kemas kini pokok DOM. JavaScript boleh digunakan untuk mengekstrak, mengulang dan menukar data kepada panggilan yang menjana HTMLElements dan nod Teks.
Tetapi enjin Ivy baharu tidak menggunakannya secara langsung, tetapi melaksanakan versinya sendiri.
DOM inkremental dalam Ivy
Enjin Ivy adalah berdasarkan konsep DOM incremental Perbezaan daripada kaedah DOM maya ialah operasi diff dilakukan secara berperingkat pada DOM (iaitu sekali nod. ) dan bukannya melaksanakan pada pokok DOM maya. Berdasarkan reka bentuk ini, DOM tambahan dan mekanisme semakan kotor dalam Angular sebenarnya berfungsi dengan baik bersama-sama.
增量 DOM 元素创建
增量 DOM 的 API 的一个独特功能是它分离了标签的打开(elementStart
)和关闭(elementEnd
),因此它适合作为模板语言的编译目标,这些语言允许(暂时)模板中的 HTML 不平衡(比如在单独的模板中,打开和关闭的标签)和任意创建 HTML 属性的逻辑。
在 Ivy 中,使用elementStart
和elementEnd
创建一个空的 Element 实现如下(在 Ivy 中,elementStart
和elementEnd
的具体实现便是ɵɵelementStart
和ɵɵelementEnd
):
export function ɵɵelement( index: number, name: string, attrsIndex?: number | null, localRefsIndex?: number ): void { ɵɵelementStart(index, name, attrsIndex, localRefsIndex); ɵɵelementEnd(); }
其中,ɵɵelementStart
用于创建 DOM 元素,该指令后面必须跟有ɵɵelementEnd()
调用。
export function ɵɵelementStart( index: number, name: string, attrsIndex?: number | null, localRefsIndex?: number ): void { const lView = getLView(); const tView = getTView(); const adjustedIndex = HEADER_OFFSET + index; const renderer = lView[RENDERER]; // 此处创建 DOM 元素 const native = (lView[adjustedIndex] = createElementNode( renderer, name, getNamespace() )); // 获取 TNode // 在第一次模板传递中需要收集匹配 const tNode = tView.firstCreatePass ? elementStartFirstCreatePass( adjustedIndex, tView, lView, native, name, attrsIndex, localRefsIndex) : tView.data[adjustedIndex] as TElementNode; setCurrentTNode(tNode, true); const mergedAttrs = tNode.mergedAttrs; // 通过推断的渲染器,将所有属性值分配给提供的元素 if (mergedAttrs !== null) { setUpAttributes(renderer, native, mergedAttrs); } // 将 className 写入 RElement const classes = tNode.classes; if (classes !== null) { writeDirectClass(renderer, native, classes); } // 将 cssText 写入 RElement const styles = tNode.styles; if (styles !== null) { writeDirectStyle(renderer, native, styles); } if ((tNode.flags & TNodeFlags.isDetached) !== TNodeFlags.isDetached) { // 添加子元素 appendChild(tView, lView, native, tNode); } // 组件或模板容器的任何直接子级,必须预先使用组件视图数据进行猴子修补 // 以便稍后可以使用任何元素发现实用程序方法检查元素 if (getElementDepthCount() === 0) { attachPatchData(native, lView); } increaseElementDepthCount(); // 对指令 Host 的处理 if (isDirectiveHost(tNode)) { createDirectivesInstances(tView, lView, tNode); executeContentQueries(tView, tNode, lView); } // 获取本地名称和索引的列表,并将解析的本地变量值按加载到模板中的相同顺序推送到 LView if (localRefsIndex !== null) { saveResolvedLocalsInData(lView, tNode); } }
可以看到,在ɵɵelementStart
创建 DOM 元素的过程中,主要依赖于LView
、TView
和TNode
。
在 Angular Ivy 中,使用了LView
和TView.data
来管理和跟踪渲染模板所需要的内部数据。对于TNode
,在 Angular 中则是用于在特定类型的所有模板之间共享的特定节点的绑定数据(享元)。
ɵɵelementEnd()
则用于标记元素的结尾:
export function ɵɵelementEnd(): void {}
对于ɵɵelementEnd()
的详细实现不过多介绍,基本上主要包括一些对 Class 和样式中@input
等指令的处理,循环遍历提供的tNode
上的指令、并将要运行的钩子排入队列,元素层次的处理等等。
组件创建与增量 DOM 指令
在增量 DOM 中,每个组件都被编译成一系列指令。这些指令创建 DOM 树并在数据更改时就地更新它们。
Ivy 在运行时编译一个组件的过程中,会创建模板解析相关指令:
export function compileComponentFromMetadata( meta: R3ComponentMetadata, constantPool: ConstantPool, bindingParser: BindingParser ): R3ComponentDef { // 其他暂时省略 // 创建一个 TemplateDefinitionBuilder,用于创建模板相关的处理 const templateBuilder = new TemplateDefinitionBuilder( constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, directiveMatcher, directivesUsed, meta.pipes, pipesUsed, R3.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds); // 创建模板解析相关指令,包括: // 第一轮:创建模式,包括所有创建模式指令(例如解析侦听器中的绑定) // 第二轮:绑定和刷新模式,包括所有更新模式指令(例如解析属性或文本绑定) const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []); // 提供这个以便动态生成的组件在实例化时,知道哪些投影内容块要传递给组件 const ngContentSelectors = templateBuilder.getNgContentSelectors(); if (ngContentSelectors) { definitionMap.set("ngContentSelectors", ngContentSelectors); } // 生成 ComponentDef 的 consts 部分 const { constExpressions, prepareStatements } = templateBuilder.getConsts(); if (constExpressions.length > 0) { let constsExpr: o.LiteralArrayExpr|o.FunctionExpr = o.literalArr(constExpressions); // 将 consts 转换为函数 if (prepareStatements.length > 0) { constsExpr = o.fn([], [...prepareStatements, new o.ReturnStatement(constsExpr)]); } definitionMap.set("consts", constsExpr); } // 生成 ComponentDef 的 template 部分 definitionMap.set("template", templateFunctionExpression); }
可见,在组件编译时,会被编译成一系列的指令,包括const
、vars
、directives
、pipes
、styles
、changeDetection
等等,当然也包括template
模板里的相关指令。最终生成的这些指令,会体现在编译后的组件中,比如之前文章中提到的这样一个Component
文件:
import { Component, Input } from "@angular/core"; @Component({ selector: "greet", template: "<div> Hello, {{name}}! </div>", }) export class GreetComponent { @Input() name: string; }
经ngtsc
编译后,产物包括该组件的.js
文件:
const i0 = require("@angular/core"); class GreetComponent {} GreetComponent.ɵcmp = i0.ɵɵdefineComponent({ type: GreetComponent, tag: "greet", factory: () => new GreetComponent(), template: function (rf, ctx) { if (rf & RenderFlags.Create) { i0.ɵɵelementStart(0, "div"); i0.ɵɵtext(1); i0.ɵɵelementEnd(); } if (rf & RenderFlags.Update) { i0.ɵɵadvance(1); i0.ɵɵtextInterpolate1("Hello ", ctx.name, "!"); } }, });
其中,elementStart()
、text()
、elementEnd()
、advance()
、textInterpolate1()
这些都是增量 DOM 相关的指令。在实际创建组件的时候,其template
模板函数也会被执行,相关的指令也会被执行。
正因为在 Ivy 中,是由组件来引用着相关的模板指令。如果组件不引用某个指令,则我们的 Angular 中永远不会使用到它。因为组件编译的过程发生在编译过程中,因此我们可以根据引用到指令,来排除未引用的指令,从而可以在 Tree-shaking 过程中,将未使用的指令从包中移除,这便是增量 DOM 可树摇的原因。
结束语
现在,我们已经知道在 Ivy 中,是通过编译器将模板编译为template
渲染函数,其中会将对模板的解析编译成增量 DOM 相关的指令。其中,在elementStart()
执行时,我们可以看到会通过createElementNode()
方法来创建 DOM。实际上,增量 DOM 的设计远不止只是创建 DOM,还包括变化检测等各种能力,关于具体的渲染过程,我们会在下一讲中进行介绍。
更多编程相关知识,请访问:编程教学!!
Atas ialah kandungan terperinci Pembelajaran sudut: analisis ringkas DOM tambahan dalam pengkompil Ivy. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Artikel ini meneruskan pembelajaran Angular, membawa anda memahami metadata dan penghias dalam Angular, dan memahami secara ringkas penggunaannya, saya harap ia akan membantu semua orang.

Angular.js ialah platform JavaScript yang boleh diakses secara bebas untuk mencipta aplikasi dinamik. Ia membolehkan anda menyatakan pelbagai aspek aplikasi anda dengan cepat dan jelas dengan memanjangkan sintaks HTML sebagai bahasa templat. Angular.js menyediakan pelbagai alatan untuk membantu anda menulis, mengemas kini dan menguji kod anda. Selain itu, ia menyediakan banyak ciri seperti penghalaan dan pengurusan borang. Panduan ini akan membincangkan cara memasang Angular pada Ubuntu24. Mula-mula, anda perlu memasang Node.js. Node.js ialah persekitaran berjalan JavaScript berdasarkan enjin ChromeV8 yang membolehkan anda menjalankan kod JavaScript pada bahagian pelayan. Untuk berada di Ub

Artikel ini akan memberi anda pemahaman yang mendalam tentang pengurus negeri Angular NgRx dan memperkenalkan cara menggunakan NgRx saya harap ia akan membantu anda!

Adakah anda tahu Angular Universal? Ia boleh membantu tapak web menyediakan sokongan SEO yang lebih baik!

Artikel ini akan berkongsi dengan anda pengalaman praktikal Angular dan mempelajari cara membangunkan sistem bahagian belakang dengan cepat menggunakan angualr digabungkan dengan ng-zorro. Saya harap ia akan membantu semua orang.

Dengan perkembangan pesat Internet, teknologi pembangunan bahagian hadapan juga sentiasa bertambah baik dan berulang. PHP dan Angular ialah dua teknologi yang digunakan secara meluas dalam pembangunan bahagian hadapan. PHP ialah bahasa skrip sebelah pelayan yang boleh mengendalikan tugas seperti memproses borang, menjana halaman dinamik dan mengurus kebenaran akses. Angular ialah rangka kerja JavaScript yang boleh digunakan untuk membangunkan aplikasi satu halaman dan membina aplikasi web berkomponen. Artikel ini akan memperkenalkan cara menggunakan PHP dan Angular untuk pembangunan bahagian hadapan, dan cara menggabungkannya

Bagaimana untuk menggunakan monaco-editor dalam sudut? Artikel berikut merekodkan penggunaan monaco-editor dalam sudut yang digunakan dalam perniagaan baru-baru ini. Saya harap ia akan membantu semua orang!

Artikel ini akan membawa anda melalui komponen bebas dalam Angular, cara mencipta komponen bebas dalam Angular, dan cara mengimport modul sedia ada ke dalam komponen bebas saya harap ia akan membantu anda!
