本篇文章給大家聊聊Angular中的視圖抽象定義,圍繞 Angular 中與視圖有關的一些定義進行介紹,希望對大家有所幫助!
作為「為大型前端專案」而設計的前端框架,Angular 其實有許多值得參考和學習的設計,本系列主要用於研究這些設計和功能的實現原理。本文主要圍繞在 Angular 中與視圖相關的一些定義進行介紹。
Angular 版本可在不同的平台上運作:在瀏覽器中、在行動平台上或在 Web Worker 中。因此,需要特定層級的抽象來介於平台特定的 API 和框架介面之間。 【相關教學推薦:《angular教學》】
Angular 中透過抽象封裝了不同平台的差異,並以下列引用類型的形式出現:ElementRef
#, TemplateRef
,ViewRef
,ComponentRef
#和ViewContainerRef
。
各抽象類別視圖定義
在閱讀原始碼的時候,如果不清楚這些定義之間的區別,很容易搞混淆。所以,這裡我們先來理解下它們之間的差異。
元素 ElementRef
ElementRef
#是最基本的抽象。如果觀察它的類別結構,可以看到它只包含與其關聯的本機元素:
export class ElementRef<T = any> { // 基础原生元素 // 如果不支持直接访问原生元素(例如当应用程序在 Web Worker 中运行时),则为 null public nativeElement: T; constructor(nativeElement: T) { this.nativeElement = nativeElement; } ... }
該API 可用於直接存取本機DOM 元素,可以比喻為document.getElementById('myId')
。但 Angular 並不鼓勵直接使用,盡可能使用 Angular 提供的模板和資料綁定。
範本 TemplateRef
在 Angular 中,範本用來定義要如何在 HTML 中渲染元件視圖的程式碼。
模板透過@Component()
裝飾器與元件類別類別關聯起來。模板程式碼可以作為template
屬性的值用內聯的方式提供,也可以透過 templateUrl
屬性連結到一個獨立的 HTML 檔案。
用TemplateRef
物件表示的其它模板用來定義一些備用視圖或內嵌視圖,它們可以來自多個不同的元件。 TemplateRef
是一組DOM 元素(ElementRef
),可在整個應用程式的視圖中重複使用:
export abstract class TemplateRef<C> { // 此嵌入视图的父视图中的 anchor 元素 abstract get elementRef(): ElementRef; // 基于此模板实例化嵌入式视图,并将其附加到视图容器 abstract createEmbeddedView(context: C): EmbeddedViewRef<C>; ... }
就其本身而言,TemplateRef
類別是一個簡單的類,僅包括:
elementRef
屬性:擁有對其宿主元素的引用createEmbeddedView
方法:它允許我們建立視圖並將其引用作為ViewRef
傳回。 模板會把純 HTML 和 Angular 的資料綁定語法、指令和模板表達式組合起來。 Angular 的元素會插入或計算那些值,以便在頁面顯示出來之前修改 HTML 元素。
Angular 中的檢視
在 Angular 中,檢視是可顯示元素的最小分組單位,它們會同時建立和銷毀。 Angular 哲學鼓勵開發人員將 UI 視為視圖的組合(而不是獨立的 html 標籤樹)。
元件(component
) 類別及其關聯的範本(template
)定義了一個視圖。在具體實作上,視圖由一個與該元件相關的ViewRef
實例表示。
ViewRef
ViewRef
表示一個Angular 視圖:
export declare abstract class ViewRef extends ChangeDetectorRef { // 销毁该视图以及与之关联的所有数据结构 abstract get destroyed(): boolean; // 报告此视图是否已被销毁 abstract destroy(): void; // 生命周期挂钩,为视图提供其他开发人员定义的清理功能 abstract onDestroy(callback: Function): any; }
其中,ChangeDetectorRef
提供變更偵測功能的基類,用於更改檢測樹收集所有要檢查更改的視圖:
export declare abstract class ChangeDetectorRef { // 当输入已更改或视图中触发了事件时,通常会将组件标记为脏(需要重新渲染) // 调用此方法以确保即使没有发生这些触发器,也要检查组件 abstract checkNoChanges(): void; // 从变更检测树中分离该视图。在重新连接分离视图之前,不会对其进行检查。 // 与 detectChanges() 结合使用可实现本地变更检测检查 abstract detach(): void; // 检查此视图及其子级,与 detach() 结合使用可实现本地更改检测检查 abstract detectChanges(): void; // 检查变更检测器及其子级,如果检测到任何变更,则抛出该异常 abstract markForCheck(): void; // 将先前分离的视图重新附加到变更检测树 // 默认情况下,视图将附加到树上 abstract reattach(): void; }
兩種類型的視圖
Angular 支援兩種類型的視圖:
(1) 連結到模板(template)的嵌入式視圖(embeddedView)。
嵌入式視圖表示視圖容器中的 Angular 視圖。模板只是保存視圖的藍圖,可以使用上述的createEmbeddedView
方法從模板實例化視圖。
(2) 連結到元件(component)的宿主視圖(hostView)。
直屬某個元件的視圖叫做宿主視圖。
宿主視圖是在動態實例化元件時建立的,可以使用ComponentFactoryResolver
動態建立實例化一個元件。在 Angular 中,每個元件都會綁定到特定的注入器實例,因此在建立元件時我們將傳遞目前的注入器實例。
視圖中各個元素的屬性可以動態修改以回應使用者的操作,而這些元素的結構(數量或順序)則不能。你可以透過在它們的視圖容器(ViewContainer
)中插入、移動或移除內嵌視圖來修改這些元素的結構。
ViewContainerRef
ViewContainerRef
是可以将一个或多个视图附着到组件中的容器:
export declare abstract class ViewContainerRef { // 锚元素,用于指定此容器在包含视图中的位置 // 每个视图容器只能有一个锚元素,每个锚元素只能有一个视图容器 abstract get element(): ElementRef; // 此视图容器的 DI abstract get injector(): Injector; // 此容器当前附加了多少视图 abstract get length(): number; // 销毁此容器中的所有视图 abstract clear(): void; // 实例化单个组件,并将其宿主视图插入此容器 abstract createComponent<C>(componentFactory: ComponentFactory<C>, index?: number, injector?: Injector, projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>; // 实例化一个嵌入式视图并将其插入 abstract createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C>; // 从此容器分离视图而不销毁它 abstract detach(index?: number): ViewRef | null; // 从此容器检索视图 abstract get(index: number): ViewRef | null; // 返回当前容器内视图的索引 abstract indexOf(viewRef: ViewRef): number; // 将视图移动到此容器中的新位置 abstract insert(viewRef: ViewRef, index?: number): ViewRef; abstract move(viewRef: ViewRef, currentIndex: number): ViewRef; // 销毁附加到此容器的视图 abstract remove(index?: number): void; }
任何 DOM 元素都可以用作视图容器,Angular 不会在元素内插入视图,而是将它们附加到绑定到ViewContainer
的元素之后。
通常,标记
ng-container
元素是标记应创建ViewContainer
的位置的最佳选择。它作为注释呈现,因此不会在 DOM 中引入多余的 HTML 元素。
通过ViewContainerRef
,可以用createComponent()
方法实例化组件时创建宿主视图,也可以用 createEmbeddedView()
方法实例化TemplateRef
时创建内嵌视图。
视图容器的实例还可以包含其它视图容器,以创建层次化视图(视图树)。
视图树(View hierarchy)
在 Angular 中,通常会把视图组织成一些视图树(view hierarchies)。视图树是一棵相关视图的树,它们可以作为一个整体行动,是 Angular 变更检测的关键部件之一。
视图树的根视图就是组件的宿主视图。宿主视图可以是内嵌视图树的根,它被收集到了宿主组件上的一个视图容器(ViewContainerRef
)中。当用户在应用中导航时(比如使用路由器),视图树可以动态加载或卸载。
视图树和组件树并不是一一对应的:
NgModule
中,也可能属于其它NgModule
组件、模板、视图与模块
在 Angular 中,可以通过组件的配套模板来定义其视图。模板就是一种 HTML,它会告诉 Angular 如何渲染该组件。
视图通常会分层次进行组织,让你能以 UI 分区或页面为单位进行修改、显示或隐藏。与组件直接关联的模板会定义该组件的宿主视图。该组件还可以定义一个带层次结构的视图,它包含一些内嵌的视图作为其它组件的宿主。
带层次结构的视图可以包含同一模块(NgModule
)中组件的视图,也可以(而且经常会)包含其它模块中定义的组件的视图。
总结
本文简单介绍了 Angular 中元素、视图、模板、组件中与视图相关的一些定义,包括ElementRef
,TemplateRef
,ViewRef
,ComponentRef
和ViewContainerRef
。
其中,视图是 Angular 中应用程序 UI 的基本构建块,它是一起创建和销毁的最小元素组。
ViewContainerRef
主要用于创建和管理内嵌视图或组件视图。组件可以通过配置模板来定义视图,与组件直接关联的模板会定义该组件的宿主视图,同时组件还可以包括内嵌视图。
更多编程相关知识,请访问:编程视频!!
以上是聊聊Angular中與視圖有關的一些定義的詳細內容。更多資訊請關注PHP中文網其他相關文章!