详解Angular 4.x NgIf 的用法(2)

ngIf 指令的源码相对比较简单,最核心的是 _updateView() 方法。而该方法中最重要的功能就是如何基于模板对象创建内嵌视图。接下来我们来分析一下 ViewContainerRef 对象的 createEmbeddedView() 方法。

ViewContainerRef - createEmbeddedView()

方法签名

// angular\packages\core\src\linker\view_container_ref.ts export abstract class ViewContainerRef { /** * 基于TemplateRef对象创建Embedded View(内嵌视图),然后根据`index`指定的值,插入到容器中。 * 如果没有指定`index`的值,新创建的视图将作为容器中的最后一个视图插入。 */ abstract createEmbeddedView<C>( templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C>; }

方法实现

// angular\packages\core\src\view\refs.ts class ViewContainerRef_ implements ViewContainerData { // ... createEmbeddedView<C>( templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C> { // 调用TemplateRef对象createEmbeddedView()方法创建EmbeddedViewRef对象 const viewRef = templateRef.createEmbeddedView(context || <any>{}); // 根据指定的index值,插入到视图容器中 this.insert(viewRef, index); return viewRef; } } // ViewContainerData接口继承于ViewContainerRef抽象类 export interface ViewContainerData extends ViewContainerRef { _embeddedViews: ViewData[]; } export interface ViewData { def: ViewDefinition; root: RootData; renderer: Renderer2; parentNodeDef: NodeDef|null; parent: ViewData|null; viewContainerParent: ViewData|null; component: any; context: any; nodes: {[key: number]: NodeData}; state: ViewState; oldValues: any[]; disposables: DisposableFn[]|null; }

通过观察 ViewContainerRef_ 类中的 createEmbeddedView() 方法,我们发现该方法内部是调用 TemplateRef 对象的 createEmbeddedView() 方法来创建内嵌视图。因此接下来我们再来分析一下 TemplateRef 对象的 createEmbeddedView() 方法。

TemplateRef - createEmbeddedView()

方法签名

// angular\packages\core\src\linker\template_ref.ts export abstract class TemplateRef<C> { abstract createEmbeddedView(context: C): EmbeddedViewRef<C>; }

方法实现

// angular\packages\core\src\view\refs.ts class TemplateRef_ extends TemplateRef<any> implements TemplateData { // ... createEmbeddedView(context: any): EmbeddedViewRef<any> { return new ViewRef_(Services.createEmbeddedView( this._parentView, this._def, this._def.element !.template !, context)); } } export interface TemplateData extends TemplateRef<any> { _projectedViews: ViewData[]; }

看完上面的源码,毫无疑问接下来我们要继续分析 Services 对象中的 createEmbeddedView() 方法。

Services - createEmbeddedView()

Services 对象定义

// angular\packages\core\src\view\types.ts export const Services: Services = { setCurrentNode: undefined !, createRootView: undefined !, createEmbeddedView: undefined !, createComponentView: undefined !, createNgModuleRef: undefined !, overrideProvider: undefined !, clearProviderOverrides: undefined !, checkAndUpdateView: undefined !, checkNoChangesView: undefined !, destroyView: undefined !, resolveDep: undefined !, createDebugContext: undefined !, handleEvent: undefined !, updateDirectives: undefined !, updateRenderer: undefined !, dirtyParentQueries: undefined !, };

Services 对象初始化

// angular\packages\core\src\view\services.ts export function initServicesIfNeeded() { if (initialized) { return; } initialized = true; const services = isDevMode() ? createDebugServices() : createProdServices(); Services.setCurrentNode = services.setCurrentNode; Services.createRootView = services.createRootView; Services.createEmbeddedView = services.createEmbeddedView; Services.createComponentView = services.createComponentView; Services.createNgModuleRef = services.createNgModuleRef; Services.overrideProvider = services.overrideProvider; Services.clearProviderOverrides = services.clearProviderOverrides; Services.checkAndUpdateView = services.checkAndUpdateView; Services.checkNoChangesView = services.checkNoChangesView; Services.destroyView = services.destroyView; Services.resolveDep = resolveDep; Services.createDebugContext = services.createDebugContext; Services.handleEvent = services.handleEvent; Services.updateDirectives = services.updateDirectives; Services.updateRenderer = services.updateRenderer; Services.dirtyParentQueries = dirtyParentQueries; }

在 initServicesIfNeeded() 方法中,会根据当前所处的模式,创建不同的 Services 对象。接下来 我们直接来看一下 createProdServices() 方法:

function createProdServices() { return { setCurrentNode: () => {}, createRootView: createProdRootView, createEmbeddedView: createEmbeddedView // 省略了其它方法 }

createEmbeddedView() 方法

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wysgdw.html