詳解Angular動(dòng)態(tài)組件
使用場(chǎng)景
我們先明確下動(dòng)態(tài)組件的使用場(chǎng)景,在代碼運(yùn)行時(shí)要?jiǎng)討B(tài)加載組件,換成普通人話(huà),代碼需要根據(jù)具體情況(比如用戶(hù)的操作,向后臺(tái)請(qǐng)求結(jié)果)確定在某些地方加載某些組件,這些組件不是靜態(tài)的(不是固定的)。
官網(wǎng)的舉例就是,構(gòu)建動(dòng)態(tài)廣告條,廣告組件不斷會(huì)推出新的,再用只支持靜態(tài)組件結(jié)構(gòu)的模板顯然是不現(xiàn)實(shí)的。
再舉一個(gè)常見(jiàn)的例子,動(dòng)態(tài)彈出框,彈出的組件是不確定的、不斷更新的,這里那里彈出個(gè)購(gòu)買(mǎi)框,那那那又需要彈出樣式選擇框,靜態(tài)組件結(jié)構(gòu)模板是不能滿(mǎn)足群眾日漸增長(zhǎng)的需求。
怎么實(shí)現(xiàn)
然后我們來(lái)找個(gè)把手,看實(shí)現(xiàn)動(dòng)態(tài)組件需要什么。
一、動(dòng)態(tài)組件放在哪
我們需要知道把動(dòng)態(tài)組件加在哪里,也就是錨點(diǎn)。那什么東西可以用來(lái)加載組件呢?
你可能會(huì)想說(shuō),組件不就加載錨點(diǎn)上嗎,錨點(diǎn)不就是DOM節(jié)點(diǎn)嗎?那當(dāng)然是加載DOM節(jié)點(diǎn)里啊。
我們先來(lái)回顧下Angular操作DOM的常見(jiàn)方法,原生JS操作DOM的方法你就不要想了,你覺(jué)得它能返回給你能加載Angular組件的對(duì)象嗎?
Angular 提供了一種叫做 DOM Query 的技術(shù),主要來(lái)源于 @ViewChild 和 @ViewChildren 裝飾器(decorators),兩者基本功能相同 。
@ViewChild: 返回單個(gè)引用,在視圖的 DOM 中查找能匹配上該選擇器的第一個(gè)元素或指令。
@ViewChildren :返回由 QueryList 對(duì)象包裝好的多個(gè)引用,在視圖的 DOM 中查找能匹配上該選擇器的所有元素或指令。
基本語(yǔ)法:
@ViewChild([reference from template], {read: [reference type]});
DOM Query 的技術(shù)查找出來(lái)的對(duì)象分為三類(lèi):
ElementRef:如果它掛載的是類(lèi)似 span 的簡(jiǎn)單 html 元素;
TemplateRef: 如果它掛載的是 template 元素;
ViewContainerRef: 無(wú)法推斷,一般要程序員要在read中指明,任何DOM元素都可以被用作為視圖容器。
我們通過(guò)官網(wǎng)查詢(xún)API可以看到只有ViewContainerRef才是可以將一個(gè)或多個(gè)視圖附著到組件中的容器,也就是只有它才可以加載組件。不過(guò)要注意的是,它是一個(gè)可以將新的組件作為其兄弟(節(jié)點(diǎn))的DOM元素(容器),是兄弟,不是父子額。
好的,我們確定了使用ViewContainerRef來(lái)加載容器,獲取ViewContainerRef有兩種方式:
第一種就是上面的通過(guò)DOM Query查詢(xún)@ViewChild獲取
<ng-container #addComp></ng-container> @ViewChild('addComp', {read: ViewContainerRef}) adComp:ViewContainerRef;
第二種就是官網(wǎng)里的例子,用依賴(lài)注入
import { Directive, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[ad-host]', }) export class AdDirective { constructor(public viewContainerRef: ViewContainerRef) { } }
錨點(diǎn)設(shè)置ng-template上,通過(guò)指令注入獲取ViewContainerRef
template: ` <div class="ad-banner-example"> <h3>Advertisements</h3> <ng-template ad-host></ng-template> </div>
二、怎么獲取組件的實(shí)例
組件加載到視圖中去,不是簡(jiǎn)單一個(gè)new就實(shí)例化,再append、insert之類(lèi)就能附加上去的就可以的。動(dòng)態(tài)組件需要編譯器事先編譯存放好起來(lái),再以ComponentFactory封裝起來(lái),之后的Component實(shí)例要通過(guò)ComponentFactory 來(lái)創(chuàng)建。大家可以看下這篇文章[譯] 關(guān)于 Angular 動(dòng)態(tài)組件你需要知道的,不過(guò)它提及的使用 SystemJsNgModuleLoader 模塊加載器已經(jīng)被淘汰了。
ComponentFactoryResolver一個(gè)簡(jiǎn)單的注冊(cè)表,映射Components到ComponentFactory可用于創(chuàng)建組件實(shí)例的生成的類(lèi)。它可用于獲取給定組件類(lèi)型的工廠(chǎng),然后使用工廠(chǎng)的create()方法創(chuàng)建該類(lèi)型的組件。
我們來(lái)看下官網(wǎng)實(shí)例代碼,以下不是完整代碼
//注入ComponentFactoryResolver constructor(private componentFactoryResolver: ComponentFactoryResolver) { } loadComponent() { ...... // 拿到可用于創(chuàng)建廣告組件實(shí)例的生成的ComponentFactory const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component); //獲取加載組件的容器 const viewContainerRef = this.adHost.viewContainerRef; viewContainerRef.clear(); // 把組件放到容器里,再傳一些參數(shù)給它 const componentRef = viewContainerRef.createComponent(componentFactory); (<AdComponent>componentRef.instance).data = adItem.data; }
你以為這就完了,你以為這樣寫(xiě)出的代碼就能運(yùn)行嗎?太年輕,讓前浪來(lái)給你說(shuō)一下要注意的幾個(gè)點(diǎn):
Angular 中的組件、指令、管道都是是被封裝在模塊中,以組件為例,如果要使用其別的模塊組件,必須別的模塊有export這個(gè)組件,而且你在自己模塊也要import其他模塊。所以官網(wǎng)例子的指令記得導(dǎo)入導(dǎo)出。
如果是動(dòng)態(tài)組件,必須把組件注冊(cè)在模塊中 entryComponents 屬性,但是就不用了export,import模塊還是需要的。
以上就是詳解Angular動(dòng)態(tài)組件的詳細(xì)內(nèi)容,更多關(guān)于Angular動(dòng)態(tài)組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Angular2實(shí)現(xiàn)組件交互的方法分析
這篇文章主要介紹了Angular2實(shí)現(xiàn)組件交互的方法,結(jié)合實(shí)例形式總結(jié)分析了Angular2中組件交互的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2017-12-12angular-ngSanitize模塊-$sanitize服務(wù)詳解
本篇文章主要介紹了angular-ngSanitize模塊-$sanitize服務(wù)詳解 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06AngularJS1.X學(xué)習(xí)筆記2-數(shù)據(jù)綁定詳解
本篇文章主要介紹了AngularJS1.X學(xué)習(xí)筆記2-數(shù)據(jù)綁定詳解,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-04-04淺談angularjs $http提交數(shù)據(jù)探索
這篇文章主要介紹了淺談angularjs $http提交數(shù)據(jù)探索,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-01-01Angular應(yīng)用tsconfig.json中的lib屬性示例解析
這篇文章主要介紹了Angular應(yīng)用tsconfig.json中的lib屬性示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07AngularJS實(shí)現(xiàn)一次監(jiān)聽(tīng)多個(gè)值發(fā)生的變化
這文章給大家介紹了如何利用AngularJS一次監(jiān)聽(tīng)多個(gè)值發(fā)生的變化,文中通過(guò)示例代碼演示,這樣更方便大家理解學(xué)習(xí),有需要的可以參考借鑒。2016-08-08使用Angular.js實(shí)現(xiàn)簡(jiǎn)單的購(gòu)物車(chē)功能
在各大購(gòu)物網(wǎng)站大家都可以簡(jiǎn)單購(gòu)物車(chē)效果演示,下面通過(guò)本文給大家分享一段代碼關(guān)于使用Angular.js實(shí)現(xiàn)簡(jiǎn)單的購(gòu)物車(chē)功能,需要的朋友可以參考下2016-11-11