您好,登錄后才能下訂單哦!
小編給大家分享一下angular4 ng-content中隱藏的內容是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
Simple example
在本文中我們使用一個示例,來演示不同的方式實現內容投影。由于許多問題與Angular 中的組件生命周期相關,因此我們的主要組件將顯示一個計數器,用于展示它已被實例化的次數:
import { Component } from '@angular/core'; let instances = 0; @Component({ selector: 'counter', template: '<h2>{{this.id}}</h2>' }) class Counter { id: number; constructor() { this.id = ++instances; } }
上面示例中我們定義了 Counter 組件,組件類中的 id 屬性用于顯示本組件被實例化的次數。接著我們繼續定義一個 Wrapper 組件:
import { Component } from '@angular/core'; @Component({ selector: 'wrapper', template: ` <div class="box"> <ng-content></ng-content> </div> ` }) class Wrapper {}
現在我們來驗證一下效果:
<wrapper> <counter></counter> <counter></counter> <counter></counter> </wrapper>
Targeted projection
有時你希望將包裝器的不同子項投影到模板的不同部分。為了處理這個問題, <ng-content>
支持一個 select
屬性,可以讓你在特定的地方投射具體的內容。該屬性支持 CSS 選擇器(my-element,.my-class,[my-attribute],...)來匹配你想要的內容。如果 ng-content
上沒有設置 select
屬性,它將接收全部內容,或接收不匹配任何其他 ng-content 元素的內容。長話短說:
import { Component } from '@angular/core'; @Component({ selector: 'wrapper', template: ` <div class="box red"> <ng-content></ng-content> </div> <div class="box blue"> <ng-content select="counter"></ng-content> </div> `, styles: [` .red {background: red;} .blue {background: blue;} `] }) export class Wrapper { }
上面示例中,我們引入了 select
屬性,來選擇投射的內容:
<wrapper> <span>This is not a counter</span> <counter></counter> </wrapper>
上述代碼成功運行后,counter
組件被正確投影到第二個藍色框中,而 span 元素最終會在全部紅色框中。請注意,目標 ng-content
會優先于 catch-all,即使它在模板中的位置靠后。
ngProjectAs
有時你的內部組件會被隱藏在另一個更大的組件中。有時你只需要將其包裝在額外的容器中即可應用 ngIf
或 ngSwitch
。無論什么原因,通常情況下,你的內部組件不是包裝器的直接子節點。為了演示上述情況,我們將 Counter 組件包裝在一個 <ng-container>
中,看看我們的目標投影會發生什么:
<wrapper> <ng-container> <counter></counter> </ng-container> </wrapper>
現在我們的 couter 組件會被投影到第一個紅色框中。因為 ng-container
容器不再匹配 select="counter"。
為了解決這個問題,我們必須使用 ngProjectAs
屬性,它可以應用于任何元素上。具體如下:
<wrapper> <ng-container ngProjectAs="counter"> <counter></counter> </ng-container> </wrapper>
通過設置 ngProjectAs
屬性,終于讓我們的 counter 組件重回藍色框的懷抱了。
Time to poke and prod
我們從一個簡單的實驗開始:將兩個 <ng-content>
塊放在我們的模板中,沒有選擇器。會出現什么情況?
頁面中會顯示一個或兩個框,如果我們包含兩個框,它們的內容是顯示 1 和 1 或 1 和 2?
<div class="box red"> <ng-content></ng-content> </div> <div class="box blue"> <ng-content></ng-content> </div>
答案是我們在最后一個 <ng-content> 中得到一個計數器,另一個是空的!在我們嘗試解釋為什么之前,讓我們再來驗證一個問題,即在 ng-content 指令的外層容器中添加 ngIf 指令:
import { Component } from '@angular/core'; @Component({ selector: 'wrapper', template: ` <button (click)="show = !show"> {{ show ? 'Hide' : 'Show' }} </button> <div class="box" *ngIf="show"> <ng-content></ng-content> </div> ` }) class Wrapper { show = true; }
乍一看,似乎正常運行。但是如果你通過按鈕進行切換操作,你會注意到計數器的值不會增加。這意味著我們的計數器組件只被實例化了一次 - 從未被銷毀和重新創建。難道這是 ngIf
指令產生的問題,讓我們測試一下 ngFor
指令,看看是否有同樣的問題:
import { Component } from '@angular/core'; @Component({ selector: 'wrapper', template: ` <div class="box" *ngFor="let item of items"> <ng-content></ng-content> </div> ` }) class Wrapper { items = [0, 0, 0]; }
以上代碼運行后與我們使用多個 <ng-content>
的效果是一樣的,只會顯示一個計數器!為什么不按照我們的預期運行?
The explanation
<ng-content>
不會 "產生" 內容,它只是投影現有的內容。你可以認為它等價于 node.appendChild(el)
或 jQuery 中的 $(node).append(el)
方法:使用這些方法,節點不被克隆,它被簡單地移動到它的新位置。因此,投影內容的生命周期將被綁定到它被聲明的地方,而不是顯示在地方。
這種行為有兩個原因:期望一致性和性能。什么 "期望的一致性" 意味著作為開發人員,可以基于應用程序的代碼,猜測其行為。假設我寫了以下代碼:
<div class="my-wrapper"> <counter></counter> </div>
很顯然計數器將被實例化一次,但現在假如我們使用第三方庫的組件:
<third-party-wrapper> <counter></counter> </third-party-wrapper>
如果第三方庫能夠控制 counter 組件的生命周期,我將無法知道它被實例化了多少次。其中唯一方法就是查看第三方庫的代碼,了解它們的內部處理邏輯。將組件的生命周期被綁定到我們的應用程序組件而不是包裝器的意義是,開發者可以掌控計數器只被實例化一次,而不用了解第三方庫的內部代碼。
性能的原因更為重要。因為 ng-content
只是移動元素,所以可以在編譯時完成,而不是在運行時,這大大減少了實際應用程序的工作量。
The solution
為了讓包裝器能夠控制其子元素的實例化,我們可以通過兩種方式完成:在我們的內容周圍使用 <ng-template>
元素,或者使用帶有 "*" 語法的結構指令。為簡單起見,我們將在示例中使用 <ng-template>
語法,我們的新應用程序如下所示:
<wrapper> <ng-template> <counter></counter> </ng-template> </wrapper>
包裝器不再使用 <ng-content>,
因為它接收到一個模板。我們需要使用 @ContentChild
訪問模板,并使用ngTemplateOutlet
來顯示它:
@Component({ selector: 'wrapper', template: ` <button (click)="show = !show"> {{ show ? 'Hide' : 'Show' }} </button> <div class="box" *ngIf="show"> <ng-container [ngTemplateOutlet]="template"></ng-container> </div> ` }) class Wrapper { show = true; @ContentChild(TemplateRef) template: TemplateRef; }
現在我們的 counter 組件,每當我們隱藏并重新顯示時都正確遞增!讓我們再驗證一下 *ngFor
指令:
@Component({ selector: 'wrapper', template: ` <div class="box" *ngFor="let item of items"> <ng-container [ngTemplateOutlet]="template"></ng-container> </div> ` }) class Wrapper { items = [0, 0, 0]; @ContentChild(TemplateRef) template: TemplateRef; }
以上是“angular4 ng-content中隱藏的內容是什么”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。