溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

angular動(dòng)態(tài)表單制作

發(fā)布時(shí)間:2020-10-13 09:55:51 來(lái)源:腳本之家 閱讀:157 作者:野生爬山虎 欄目:web開(kāi)發(fā)

源碼:https://github.com/Karin001/ngx-dynamic-form

angular動(dòng)態(tài)表單制作

動(dòng)態(tài)表單使用場(chǎng)景

有時(shí)候我們需要一個(gè)靈活的表單,這個(gè)表單可以根據(jù)用戶的選擇,或者服務(wù)器返回的信息進(jìn)行重新配置,比如:增加或刪除一組input元素、一組select元素,等等。

在這樣的情況下,如果一開(kāi)始就在模板里寫下所有的表單,利用一個(gè)ngif樹(shù)狀結(jié)構(gòu)進(jìn)行選擇控制,程序會(huì)變得比較冗余。

這時(shí)。程序最好是能夠根據(jù)用戶的選擇(driven by configuration)或者服務(wù)器的響應(yīng),自動(dòng)生成所需要的表單。這就是動(dòng)態(tài)表單要處理的業(yè)務(wù)。

組件生成的相關(guān)概念組件的兩個(gè)構(gòu)成

要?jiǎng)討B(tài)生成表單,需要先理解組件是如何生成的。

一個(gè)angular組件由兩部分所組成。

Wrapper

Wrapper能夠與組件進(jìn)行交互,當(dāng)一個(gè)Wrapper初始化完成后,就已經(jīng)幫我們實(shí)例化了一個(gè)組件。同時(shí),它也負(fù)責(zé)組件的change detection,以及觸發(fā)鉤子函數(shù)比如ngOnInit,ngOnChanges。

View

View負(fù)責(zé)呈現(xiàn)渲染過(guò)后的模板,將組件的外貌展示出來(lái),并且能夠觸發(fā)Wrapper的change detection。一個(gè)組件可以有多個(gè)view,每一個(gè)view可以通過(guò)調(diào)用angular提供的兩個(gè)函數(shù)自行生成和銷毀,這個(gè)過(guò)程不用頂層的視圖參與。

組件的通常加載方式(非動(dòng)態(tài)加載方式)

通常情況下,我們都是把組件內(nèi)嵌到根組件或者另一個(gè)組件當(dāng)中使用。嵌入的組件稱為子組件,被嵌入的稱為父組件。這時(shí),當(dāng)我們的子組件代碼在被編譯時(shí),會(huì)生成一個(gè)組件工廠component factory(這是angular核心類ComponentFactory的一個(gè)實(shí)例),和一個(gè)hsot view,host view負(fù)責(zé)本組件在父組件視圖內(nèi)生成該組件的dom節(jié)點(diǎn),以及生成該組件的wrapper和view。

動(dòng)態(tài)加載組件

而當(dāng)我們想要將一個(gè)動(dòng)態(tài)組件插入某個(gè)組件視圖時(shí),則無(wú)法取得這個(gè)動(dòng)態(tài)組件的實(shí)例,因?yàn)檫@些是非動(dòng)態(tài)組件編譯器做的事。

實(shí)現(xiàn)動(dòng)態(tài)組件

angular提供了一些函數(shù)解決上面的難題,要使用這些函數(shù)我們需要注入兩個(gè)對(duì)象。

constructor(
 private componentFactoryResolver: ComponentFactoryResolver,
 private viewcontainerRef: ViewContainerRef,
 ) {
  
 }

我們注入了ComponentFactoryResolver,和ViewContainerRef。

ComponentFactoryResolver上提供了一個(gè)方法(resolveComponentFactory()),該方法接收一個(gè)組件類作為參數(shù),生成一個(gè)基于該組件類的組件工廠,也就是我們之前提到的那個(gè)組件工廠。

ViewContainerRef提供了一個(gè)方法(createComponent()),該方法接收組件工廠作為參數(shù),在該視圖中生成子組件。(我個(gè)人的理解是它處理了host view所做的事,為組件生成了wrapper和view)

實(shí)現(xiàn)動(dòng)態(tài)表單

上文簡(jiǎn)要的介紹了實(shí)現(xiàn)動(dòng)態(tài)組件的一些技術(shù),現(xiàn)在開(kāi)始思考如何做一個(gè)動(dòng)態(tài)表單。

具體思路

我們想要做出一個(gè)獨(dú)立的動(dòng)態(tài)表單模塊,當(dāng)我們想要使用動(dòng)態(tài)表單時(shí),只需簡(jiǎn)單引入這個(gè)模塊,稍加配置即可使用。

我們希望這個(gè)模塊做好了后,在頂層使用者的角度會(huì)是這樣一個(gè)工作流程:

angular動(dòng)態(tài)表單制作

我們可以很容易的做出一個(gè)具有輸入屬性的組件,問(wèn)題的核心在于這個(gè)組件是如何根據(jù)輸入屬性生成我們想要的表單。

也就是說(shuō),是它自己調(diào)用ComponentFactoryResolver和ViewContainerRef進(jìn)行組件的動(dòng)態(tài)生成,還是交給別人處理。

下圖是實(shí)現(xiàn)思路:

angular動(dòng)態(tài)表單制作

實(shí)際上我們把動(dòng)態(tài)表單拆分成了一個(gè)個(gè)小的動(dòng)態(tài)組件(不預(yù)先加載),由外層的一個(gè)組件充當(dāng)一個(gè)容器,所有的動(dòng)態(tài)組件都會(huì)在里面進(jìn)行生成和銷毀,他們共同組成了一個(gè)動(dòng)態(tài)表單。調(diào)用ComponentFactoryResolver和ViewContainerRef生成組件的的這部分邏輯沒(méi)有集成在外層容器中,而是交給了一個(gè)自定義的指令和ng-container。因?yàn)橹噶顩](méi)有視圖,他通過(guò)注入ViewContainerRef獲取到的是宿主的視圖容器。由于ng-container不會(huì)被渲染,所以獲取到的視圖容器就是外層組件容器的視圖容器。

這么處理的好處就是不需要由外層組件統(tǒng)一對(duì)各個(gè)拆分的動(dòng)態(tài)組件進(jìn)行管理,相當(dāng)于是由動(dòng)態(tài)組件自己進(jìn)行管理。

外層組件容器大概會(huì)是下面這樣:

<form>
 <ng-container *ngFor="let config of configs" [自定義指令] >
 </ng-container>
</form>

configs是用戶的配置數(shù)據(jù),自定義指令寄宿在ng-container中,根據(jù)config渲染出各自的動(dòng)態(tài)組件,而ng-container是透明的。

看一下代碼目錄結(jié)構(gòu),最后會(huì)是這個(gè)樣子

angular動(dòng)態(tài)表單制作

以上就是大體的實(shí)現(xiàn)思路了,具體還有許多細(xì)節(jié)可以關(guān)注文章開(kāi)頭提到的那兩篇文章,講的很詳細(xì)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI