通过单步调试的方式学习 Angular 中 TView 和 LView 的概念
問題描述
本文涉及到的代碼位置:https://github.com/wangzixi-diablo/ngDynamic
看這樣一組 parent Component 和 child Component:
@Component({selector: 'child',template: `<span>I am a child.</span>`})export class ChildViewComponent {}@Component({selector: 'parent',template: `<div>projected content: <ng-content></ng-content></div>`})export class ParentComponent {}@Component({selector: 'demo',template: `<parent id="p1"><child id="c1"></child></parent><child id="c2"></child>`})export class Demo {}其中 parent Component 定義了一個內容投影區域,通過下列高亮代碼,將子 Component 的內容投射進來:
即該區域:
最后的運行時效果:
問題分析
當上述應用被 load 但尚未完成 bootstrap 時,Ivy 將其解析為如下的 TView:
const tChildComponentView = new TView(tData: [new TElementNode(‘span’),new TTextNode(‘I am a child.’),],…, ); const tParentComponentView = new TView(tData: [new TElementNode(‘div’),new TTextNode(‘projected content: ‘),new TProjectionNode(),],…, ); const tDemoAppView = new TView(tData: [new TElementNode(‘parent’, [‘id’, ‘p1’]),new TElementNode(‘child’, [‘id’, ‘c1’]),new TElementNode(‘child’, [‘id’, ‘c2’]),],…, )接下來的步驟就是 bootstrap,具體的邏輯就是基于 TView 創建 LView:
const lParentComponentView_p1 = new LView(tParentComponentView,new ParentComponent(…),document.createElement(‘div’),document.createText(‘projected content: ‘), ); const lChildComponentView_c1 = new LView(tChildComponentView,new ChildComponent(…),document.createElement(‘span’),document.createText(‘I am a child.’), ); const lChildComponentView_c2 = new LView(tChildComponentView,new ChildComponent(…),document.createElement(‘span’),document.createText(‘I am a child.’), ); const lDemoAppView = new LView(tDemoAppView,new DemoApp(…),document.createElement(‘parent’),lParentComponentView_p1,document.createElement(‘child’),lChildComponentView_c1,document.createElement(‘child’),lChildComponentView_c2, )上述邏輯在調試器里如下圖所示:
其中 JerryAppComponent 被維護為 bootstrap Component:
上述代碼展示了 TView 和 LView 二者的區別。
再看 ChildComponent,TView 的實例只有一個,而 LView 的實例卻有兩個,因為 ChildComponent 被使用了兩次。 另一個關鍵區別是 LView 只存儲特定于該組件實例的數據——例如組件實例和關聯的 DOM 節點。 TView 存儲在組件的所有實例之間共享的信息——例如需要創建哪些 DOM 節點。
在上面的示例中,LView 顯示為一個類(new LView(…)。實際上,我們將它存儲為一個數組([…])。將 LView 存儲為一個數組是出于內存性能的原因。 每個模板都有不同數量的 DOM 節點和子組件/指令,將其存儲在數組中是最有效的方式。
使用數組進行存儲的含義是不清楚在數組中的哪個位置存儲實例數據。 TData 用于描述 LView 中每個位置存儲的內容。 所以 LView 本身不足以推理,因為它在沒有上下文的情況下存儲值。 TView 描述了組件需要什么,但它不存儲實例信息。 通過將 LView 和 TView 放在一起,Ivy 可以訪問和推理 LView 中的值。 LView 存儲值,而 TView 存儲 LView 中值的含義,類似元數據或者 schema 的概念。
為簡單起見,LView 僅存儲 DOM 節點。 在實踐中,LView 還存儲綁定、注入器、凈化器以及與視圖狀態相關的任何其他內容(在 TView/TData 中具有相應的條目。)
總結
考慮 View 和 View 的一種方法是將這些概念與面向對象的編程聯系起來。 TView 就像類,而 View 就像類實例。
總結
以上是生活随笔為你收集整理的通过单步调试的方式学习 Angular 中 TView 和 LView 的概念的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何将苹果手机数据导入华为手机
- 下一篇: 我的世界弩怎么做(最详细的官方我的)