欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Angular 4.x NgIf 的用法

 更新時(shí)間:2017年05月22日 09:42:43   作者:semlinker  
本篇文章主要介紹了詳解Angular 4.x NgIf,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

NgIf 指令作用

ngIf 指令用于根據(jù)表達(dá)式的值,在指定位置渲染 then 或 else 模板的內(nèi)容。

  1. then 模板除非綁定到不同的值,否則默認(rèn)是 ngIf 指令關(guān)聯(lián)的內(nèi)聯(lián)模板。
  2. else 模板除非綁定對(duì)應(yīng)的值,否則默認(rèn)是 null。

NgIf 指令語(yǔ)法

簡(jiǎn)單形式

<!--語(yǔ)法糖-->
<div *ngIf="condition">...</div>
<!--Angular 2.x中使用template-->
<ng-template [ngIf]="condition"><div>...</div></ng-template>

使用else塊

<div *ngIf="condition; else elseBlock">...</div>
<ng-template #elseBlock>...</ng-template>

使用then和else塊

<div *ngIf="condition; then thenBlock else elseBlock"></div>
<ng-template #thenBlock>...</ng-template>
<ng-template #elseBlock>...</ng-template>

使用as語(yǔ)法

<div *ngIf="condition as value; else elseBlock">{{value}}</div>
<ng-template #elseBlock>...</ng-template>

NgIf 使用示例

@Component({
 selector: 'ng-if-then-else',
 template: `
  <button (click)="show = !show">{{show ? 'hide' : 'show'}}</button>
  <button (click)="switchPrimary()">Switch Primary</button>
    show = {{show}}
  <br>
  <div *ngIf="show; then thenBlock; else elseBlock">this is ignored</div>
  <ng-template #primaryBlock>Primary text to show</ng-template>
  <ng-template #secondaryBlock>Secondary text to show</ng-template>
  <ng-template #elseBlock>Alternate text while primary text is hidden</ng-template>
 `
})
class NgIfThenElse implements OnInit {
 thenBlock: TemplateRef<any> = null;
 show: boolean = true;
 
 @ViewChild('primaryBlock')
 primaryBlock: TemplateRef<any> = null;
 @ViewChild('secondaryBlock')
 secondaryBlock: TemplateRef<any> = null;
 
 switchPrimary() {
  this.thenBlock = this.thenBlock === this.primaryBlock ? 
   this.secondaryBlock : this.primaryBlock;
 }
 
 ngOnInit() { 
   this.thenBlock = this.primaryBlock;
 }
}

基礎(chǔ)知識(shí)

TemplateRef
TemplateRef 實(shí)例用于表示模板對(duì)象,TemplateRef 抽象類(lèi)的定義如下:

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

ViewContainerRef

ViewContainerRef 實(shí)例提供了 createEmbeddedView() 方法,該方法接收 TemplateRef 對(duì)象作為參數(shù),并將模板中的內(nèi)容作為容器 (comment 元素) 的兄弟元素,插入到頁(yè)面中。

NgIfContext

NgIfContext 實(shí)例用于表示 NgIf 上下文。

// angular\packages\common\src\directives\ng_if.ts
export class NgIfContext {
 public $implicit: any = null;
 public ngIf: any = null;
}

NgIf 源碼分析

NgIf 指令定義

@Directive({
  selector: '[ngIf]' // 屬性選擇器 - <ng-template [ngIf]="condition">
})

NgIf 類(lèi)私有屬性及構(gòu)造函數(shù)

export class NgIf {
 // 創(chuàng)建NgIfContext上下文
 private _context: NgIfContext = new NgIfContext();
 // 表示then模板對(duì)象
 private _thenTemplateRef: TemplateRef<NgIfContext>|null = null;
 // 表示else模板對(duì)象
 private _elseTemplateRef: TemplateRef<NgIfContext>|null = null;

 // 表示根據(jù)then模板創(chuàng)建的EmbeddedViewRef視圖
 private _thenViewRef: EmbeddedViewRef<NgIfContext>|null = null;
 // 表示根據(jù)else模板創(chuàng)建的EmbeddedViewRef視圖
 private _elseViewRef: EmbeddedViewRef<NgIfContext>|null = null;

 constructor(
  private _viewContainer: ViewContainerRef, 
  templateRef: TemplateRef<NgIfContext>) {
   this._thenTemplateRef = templateRef; // then模板的默認(rèn)值為ngIf指令關(guān)聯(lián)的內(nèi)聯(lián)模板
 }
}

NgIf 類(lèi)輸入屬性

@Input()
set ngIf(condition: any) {
  this._context.$implicit = this._context.ngIf = condition;
  this._updateView(); // 更新視圖
}

@Input()
set ngIfThen(templateRef: TemplateRef<NgIfContext>) {
  this._thenTemplateRef = templateRef;
  this._thenViewRef = null; // 清除之前創(chuàng)建的視圖
  this._updateView();
}

@Input()
set ngIfElse(templateRef: TemplateRef<NgIfContext>) {
  this._elseTemplateRef = templateRef;
  this._elseViewRef = null; // 清除之前創(chuàng)建的視圖
  this._updateView();
}

_updateView() 私有方法

// 更新視圖
private _updateView() {
 // this._context.$implicit = this._context.ngIf = condition
 // 若condition表達(dá)式的值為truthy
 if (this._context.$implicit) {
 // 若_thenViewRef為null且_thenTemplateRef存在,則創(chuàng)建_thenViewRef內(nèi)嵌視圖
   if (!this._thenViewRef) {
    this._viewContainer.clear();
    this._elseViewRef = null;
    if (this._thenTemplateRef) {
     this._thenViewRef =
       this._viewContainer.createEmbeddedView(this._thenTemplateRef,
        this._context);
    }
   }
  } else { // condition表達(dá)式的值為falsy
   // 若_elseViewRef為null且_elseTemplateRef存在,則創(chuàng)建_elseViewRef內(nèi)嵌視圖
   if (!this._elseViewRef) {
    this._viewContainer.clear();
    this._thenViewRef = null;
    if (this._elseTemplateRef) {
     this._elseViewRef =
       this._viewContainer.createEmbeddedView(this._elseTemplateRef, 
        this._context);
    }
   }
  }
}

ngIf 指令的源碼相對(duì)比較簡(jiǎn)單,最核心的是 _updateView() 方法。而該方法中最重要的功能就是如何基于模板對(duì)象創(chuàng)建內(nèi)嵌視圖。接下來(lái)我們來(lái)分析一下 ViewContainerRef 對(duì)象的 createEmbeddedView() 方法。

ViewContainerRef - createEmbeddedView()

方法簽名

// angular\packages\core\src\linker\view_container_ref.ts
export abstract class ViewContainerRef {
  /**
  * 基于TemplateRef對(duì)象創(chuàng)建Embedded View(內(nèi)嵌視圖),然后根據(jù)`index`指定的值,插入到容器中。 
  * 如果沒(méi)有指定`index`的值,新創(chuàng)建的視圖將作為容器中的最后一個(gè)視圖插入。
  */ 
 abstract createEmbeddedView<C>(
   templateRef: TemplateRef<C>, 
   context?: C, index?: number):
   EmbeddedViewRef<C>;
}

方法實(shí)現(xiàn)

// angular\packages\core\src\view\refs.ts
class ViewContainerRef_ implements ViewContainerData {
  // ...
  createEmbeddedView<C>(
   templateRef: TemplateRef<C>, 
   context?: C, index?: number):
   EmbeddedViewRef<C> {
    // 調(diào)用TemplateRef對(duì)象createEmbeddedView()方法創(chuàng)建EmbeddedViewRef對(duì)象
    const viewRef = templateRef.createEmbeddedView(context || <any>{});
     // 根據(jù)指定的index值,插入到視圖容器中
    this.insert(viewRef, index);
    return viewRef;
 }
}

// ViewContainerData接口繼承于ViewContainerRef抽象類(lèi)
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;
}

通過(guò)觀察 ViewContainerRef_ 類(lèi)中的 createEmbeddedView() 方法,我們發(fā)現(xiàn)該方法內(nèi)部是調(diào)用 TemplateRef 對(duì)象的 createEmbeddedView() 方法來(lái)創(chuàng)建內(nèi)嵌視圖。因此接下來(lái)我們?cè)賮?lái)分析一下 TemplateRef 對(duì)象的 createEmbeddedView() 方法。

TemplateRef - createEmbeddedView()

方法簽名

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

方法實(shí)現(xiàn)

// 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[];
}

看完上面的源碼,毫無(wú)疑問(wèn)接下來(lái)我們要繼續(xù)分析 Services 對(duì)象中的 createEmbeddedView() 方法。

Services - createEmbeddedView()

Services 對(duì)象定義

// 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 對(duì)象初始化

// 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() 方法中,會(huì)根據(jù)當(dāng)前所處的模式,創(chuàng)建不同的 Services 對(duì)象。接下來(lái) 我們直接來(lái)看一下 createProdServices() 方法:

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

createEmbeddedView() 方法

// angular\packages\core\src\view\view.ts
export function createEmbeddedView(
  parent: ViewData, anchorDef: NodeDef, viewDef: ViewDefinition, context?: any): ViewData {
 // embedded views are seen as siblings to the anchor, so we need
 // to get the parent of the anchor and use it as parentIndex.
 // 創(chuàng)建ViewData對(duì)象
 const view = createView(parent.root, parent.renderer, parent, anchorDef, viewDef);
 // 初始化ViewData對(duì)象-設(shè)置component及context屬性的值
 initView(view, parent.component, context);
 // 創(chuàng)建視圖中的節(jié)點(diǎn),即設(shè)置view.nodes數(shù)組的屬性值
 // const nodes = view.nodes; for(...) { ...; nodes[i] = nodeData; }
 createViewNodes(view);
 return view;
}

此時(shí)發(fā)現(xiàn)如果完整分析所有的方法,會(huì)涉及太多的內(nèi)容。源碼分析就到此結(jié)束,有興趣的讀者請(qǐng)自行閱讀源碼哈(請(qǐng)各位讀者見(jiàn)諒)。接下來(lái)我們來(lái)總結(jié)一下 createEmbeddedView() 方法調(diào)用流程:

ViewContainerRef_ -> createEmbeddedView()
  => TemplateRef_ -> createEmbeddedView()
  => Services -> createEmbeddedView()
   => Call createEmbeddedView()

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:

相關(guān)文章

  • 使用xampp將angular項(xiàng)目運(yùn)行在web服務(wù)器的教程

    使用xampp將angular項(xiàng)目運(yùn)行在web服務(wù)器的教程

    這篇文章主要介紹了使用xampp將angular項(xiàng)目運(yùn)行在web服務(wù)器,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • div實(shí)現(xiàn)自適應(yīng)高度的textarea實(shí)現(xiàn)angular雙向綁定

    div實(shí)現(xiàn)自適應(yīng)高度的textarea實(shí)現(xiàn)angular雙向綁定

    本文主要介紹了div實(shí)現(xiàn)自適應(yīng)高度的textarea,實(shí)現(xiàn)angular雙向綁定的方法。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-01-01
  • 如何用DevUI搭建自己的Angular組件庫(kù)

    如何用DevUI搭建自己的Angular組件庫(kù)

    DevUI 是一款面向企業(yè)中后臺(tái)產(chǎn)品的開(kāi)源前端解決方案,它倡導(dǎo)沉浸、靈活、至簡(jiǎn)的設(shè)計(jì)價(jià)值觀,提倡設(shè)計(jì)者為真實(shí)的需求服務(wù),為多數(shù)人的設(shè)計(jì),拒絕嘩眾取寵、取悅眼球的設(shè)計(jì)。如果你正在開(kāi)發(fā) ToB 的工具類(lèi)產(chǎn)品,DevUI 將是一個(gè)很不錯(cuò)的選擇!
    2021-05-05
  • 走進(jìn)AngularJs之過(guò)濾器(filter)詳解

    走進(jìn)AngularJs之過(guò)濾器(filter)詳解

    本篇文章主要介紹了AngularJs之過(guò)濾器(filter)詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-02-02
  • angular6?Error:Debug?Failure?at?typeToString解決分析

    angular6?Error:Debug?Failure?at?typeToString解決分析

    這篇文章主要為大家介紹了angular6?Error:Debug?Failure?at?typeToString解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 淺談AngularJs指令之scope屬性詳解

    淺談AngularJs指令之scope屬性詳解

    下面小編就為大家?guī)?lái)一篇淺談AngularJs指令之scope屬性詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • monaco?editor在Angular的使用詳解

    monaco?editor在Angular的使用詳解

    這篇文章主要為大家介紹了monaco?editor在Angular的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • AngularJS基礎(chǔ) ng-selected 指令簡(jiǎn)單示例

    AngularJS基礎(chǔ) ng-selected 指令簡(jiǎn)單示例

    本文主要介紹AngularJS ng-selected 指令,這里對(duì)ng-selected 指令的基礎(chǔ)資料做了詳細(xì)介紹,并附有示例代碼,有需要的小伙伴可以參考下
    2016-08-08
  • AngularJS中$http的交互問(wèn)題

    AngularJS中$http的交互問(wèn)題

    本篇文章主要介紹了AngularJS中$http的交互問(wèn)題 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • 利用Angular.js限制textarea輸入的字?jǐn)?shù)

    利用Angular.js限制textarea輸入的字?jǐn)?shù)

    相信在大家已經(jīng)學(xué)習(xí)了足夠多關(guān)于AngularJS的知識(shí)后,就可以開(kāi)始創(chuàng)建第一個(gè)AngularJS應(yīng)用程序,這篇文章通過(guò)示例給大家介紹如何利用Angular.js限制textarea輸入的字?jǐn)?shù),有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。
    2016-10-10

最新評(píng)論