Angular Renderer (渲染器)的具体使用(5)
步骤一
当 Angular 在创建组件视图时,会根据 nodeDef.element
对象的 componentRendererType
属性值,来创建组件的渲染器。接下来我们先来看一下 NodeDef
、 ElementDef
和 RendererType2
接口定义:
// packages/core/src/view/types.ts // 视图中节点的定义 export interface NodeDef { bindingIndex: number; bindings: BindingDef[]; bindingFlags: BindingFlags; outputs: OutputDef[]; element: ElementDef|null; // nodeDef.element provider: ProviderDef|null; // ... } // 元素的定义 export interface ElementDef { name: string|null; attrs: [string, string, string][]|null; template: ViewDefinition|null; componentProvider: NodeDef|null; // 设置组件渲染器的类型 componentRendererType: RendererType2|null; // nodeDef.element.componentRendererType componentView: ViewDefinitionFactory|null; handleEvent: ElementHandleEventFn|null; // ... } // packages/core/src/render/api.ts // RendererType2 接口定义 export interface RendererType2 { id: string; encapsulation: ViewEncapsulation; // Emulated、Native、None styles: (string|any[])[]; data: {[kind: string]: any}; }
步骤二
获取 componentRendererType
的属性值后,如果该值为 null
的话,则直接使用 parentView.root
属性值对应的 renderer
对象。若该值不为空,则调用 parentView.root
对象的 rendererFactory()
方法创建 renderer
对象。
通过上面分析,我们发现不管走哪条分支,我们都需要使用 parentView.root
对象,然而该对象是什么特殊对象?我们发现 parentView
的数据类型是 ViewData
,该数据接口定义如下:
// packages/core/src/view/types.ts export interface ViewData { def: ViewDefinition; root: RootData; renderer: Renderer2; nodes: {[key: number]: NodeData}; state: ViewState; oldValues: any[]; disposables: DisposableFn[]|null; // ... }
通过 ViewData
的接口定义,我们终于发现了 parentView.root
的属性类型,即 RootData
:
// packages/core/src/view/types.ts export interface RootData { injector: Injector; ngModule: NgModuleRef<any>; projectableNodes: any[][]; selectorOrNode: any; renderer: Renderer2; rendererFactory: RendererFactory2; errorHandler: ErrorHandler; sanitizer: Sanitizer; }
那好,现在问题来了:
- 什么时候创建
RootData
对象? - 怎么创建
RootData
对象?
什么时候创建 RootData
对象?
当创建根视图的时候会创建 RootData,在开发环境会调用 debugCreateRootView()