摘要:原文的第四篇文章中的一個重要元素在上一篇文章中沒有涉及,使用高階組件中的常用模式可以將組件中的公用邏輯分離出來。同時,因為組件的模板并不存在任何的變動,我們可以將它轉化為一個指令,這樣我們可以以更加靈活的方式來使用它。
03-b Enhance Components with Directives
原文: Enhance Components with Directives
Kent C. Dodds的第四篇文章中的一個重要元素在上一篇文章中沒有涉及,使用withToggle高階組件(HoC, react中的常用模式)可以將
雖然上一篇文章中上面提及的三個組件并沒有太多的公用邏輯,可以萬一它們有公用邏輯呢?如果我們想要提供更加聲明式的功能,比如能夠顯式的聲明它們使用的
同時,因為
允許我們的
允許通過withToggle`指令顯式地設置`
將
@Directive({ exportAs: "toggle", selector: "toggle, [toggle]", }) export class ToggleDirective {}
你可能注意到了,指令的選擇器允許toggle指令可以以標簽名和屬性名的形式來使用。對于exportAs關鍵字是必須要提供的,因為這是當我們需要在別的指令或者組件能夠獲取toggle指令引用的名字,會在這個系列文章的第5章詳細刪除exportAs(Handle Template Reference Variables with Directives)。
2)withToggle指令在這個新的指令中,我們將會封裝關于如何選取需要綁定某個toggle指令實例的邏輯。
首先,我們的設想是這樣的,每一個組件注入withToggle指令,而不是直接注入最鄰近的父toggle指令。同時每個使用withToggle指令的組件通過使用withToggle.toggle來訪問它所綁定的toggle指令的實例,如下:
@Component({ selector: "toggle-off", template: ``, }) export class ToggleOffComponent { constructor(public withToggle: WithToggleDirective) {} }
其次,withToggle指令將它自身與toggle指令的選擇器綁定(就是兩個指令的選擇器是相同的),同時增加一個額外的選擇器[withToggle],如下:
@Directive({ exportAs: "withToggle", selector: "toggle, [toggle], [withToggle]", }) export class WithToggleDirective //...
現(xiàn)在withToggle指令為它的子組件們提供所綁定的toggle指令實例,無論這個實例是顯示綁定的,還是默認的父toggle指令。關于其中實現(xiàn)的具體細節(jié),可以參考文章最后的附錄部分。
成果我們的app.component.html現(xiàn)在可以通過三種不同的使用方式來展現(xiàn)內(nèi)容。
1)基本......
注意#firstToggle和#secondToggle視圖變量是如何使用toggle組件的,前者使用屬性聲明的方式,后者使用標簽名聲明方式,無論怎樣,它們都按理想中那樣運行。
而且,#secondToggle是嵌套在#firstToggle中的,所以它的子組件使用的是它本身的開關狀態(tài),而非#firstToggle中的,這符合我們的預期。
2)顯式引用First:
On Off
這里沒有任何toggle指令是當前p標簽的子組件的祖先,但是通過withToggle指令,我們可以讓所有的子組件使用#firstToggle的toggle指令實例。
3)自定義組件withToggle指令甚至可以通過DI機制注入到內(nèi)部的任何自定義組件中,如
withToggle的實現(xiàn),是一個標準的指令聲明方式,除了它的構造方法,如下:
constructor( @Host() @Optional() private toggleDirective: ToggleDirective, ) {}
值得注意的有兩點:
@Host():這個裝飾器的作用是,可以限制從屬于當前指令的DI注入器,僅注入綁定到某個滿足特定條件指定或者組件上的toggle指令實例,而不是從它的祖先組件們中注入。(這里選擇器為空,則為宿主對象)
@Optional():這個裝飾器會告訴編譯器,當注入器沒有找到任何可注入的toggle指令時,不要拋出錯誤(如果我們手動的指定某個引用),這樣在它無法被注入時,使它保持undefined即可。
現(xiàn)在我們可以很容易的理解在ngOnChanges生命周期鉤子函數(shù)中的代碼的作用,
this.toggle = this.withToggle || this.toggleDirective;
如果我們的@Input()被指定,那么使用它的值
如果沒有,則嘗試去使用在當前宿主對象上注入的toggle指令實例
如果沒有,則使用undefined
當前的this指定withToggle本身,所以擁有它引用的子組件都可以訪問它。
在線代碼演示(自備梯子): https://stackblitz.com/edit/a...
譯者注在這一節(jié)中,主要進行了以下幾方面的改進:
簡化toggle本身,因為它一直是作為一個容器組件使用的,所以完全可以以指令(可以理解為沒有模板的組件)的形式存在
依賴注入(DI)的機制雖然很強大,但是受限于它的運作原理(關于具體的運作原理可以參考官方文檔)。這里原作者使用一個額外的withToggle指令作為中間件,來作為toggle指令的托管容器。這部分理解起來可能需要先了解一下視圖變量和exportAs的相關的知識
對于toggle指令實例的獲取邏輯,采用平穩(wěn)退化的策略,就好比人在實際生活中思考問題的方式一樣。
這種開發(fā)模式,在實際工作中,我有一次在重構公司項目中一個關于表單組件的過程中曾使用過,之所以使用這種方式,是因為在表單組件中,會存在一些關于聯(lián)動校驗或者分組的需求,如果將這部門邏輯封裝為service或者直接寫在controller內(nèi)部,越到后面會發(fā)現(xiàn)邏輯復雜度越高,從而越來越難維護。
使用這種模式,將復雜的邏輯劃分成小的顆粒,再封裝為獨立的指令,在需要用到這些邏輯的組件中注入這些指令即可,指令的特點就是一般都會比較簡潔,只會做一些簡單的事情,相比之下,維護一個十分復雜的service和維護若干簡單的指令,我更傾向于后者。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90803.html
摘要:為了適應表單校驗的靈活性,我們使用這種模式會事半功倍,提供校驗信息的組件僅僅聲明渲染表單錯誤提示信息需要設計的狀態(tài)變量即可,比如等等,對于錯誤信息的文案及樣式,統(tǒng)統(tǒng)交由錯誤提示組件的使用者完成。 06 Use Render Props最近在React社區(qū)中引起了轟動,但是與之類似的模式在Angular中似乎并沒有得到太多關注。我在之前寫的文章提及過,TemplateRefs就是Ang...
摘要:原文如那樣,我們將使用一個相對簡單的組件來說明這些模式。組件的職責是僅僅是管理一個簡單的布爾值狀態(tài)屬性。文件夾并且特別是,將針對庫在不同的情形下的使用做出相應的改變。 寫在前頭 Angular到現(xiàn)在已經(jīng)到5.x的版本了,對于MVVM框架我首先接觸的是angularjs后來又轉為react,之后換了工作因項目技術棧的原因又轉換到之前的angularjs,在實際工作中實施了公司幾個比較重要...
摘要:目標提供一些方法或指令給組件使用者,使其可以與所提供的元素交互并修改它們。這個指令擁有一個屬性并與組件共享,該屬性將決定屬性的值是還是。 07 使用 Content Directives 原文: Use Content Directives 因為父組件會提供所有相關的 UI 元素(比如這里的 button),所以 toggle 組件的開發(fā)者可能無法滿足組件使用者的一些附加需求,比如,...
摘要:同時,依賴注入機制是依附于組件本身存在的,并不依附于模板的層級關系,因此不會面臨問題二的困擾。對于木偶組件本身,往往作為消費者存在,這種情況下使用機制可能會達到更好的效果。 03-a Communicate Between Components Using Dependency Injection 原文: Communicate Between Components Using Dep...
摘要:相關話題裝飾器將會返回在組件標簽包含的內(nèi)容中,第一個符合選擇器的子組件或者子指令的引用,比如。或者裝飾器是用來獲取在組件內(nèi)部模板中使用的單個或者多個組件的。 02 Write Compound Components 原文: Write Compound Components 目標 我們需要實現(xiàn)的需求是能夠使使用者通過組件動態(tài)的改變包含在它內(nèi)部的內(nèi)容。 實現(xiàn) 我們可以把toggle抽象...
閱讀 2810·2021-10-26 09:48
閱讀 1671·2021-09-22 15:22
閱讀 4029·2021-09-22 15:05
閱讀 608·2021-09-06 15:02
閱讀 2607·2019-08-30 15:52
閱讀 2107·2019-08-29 18:38
閱讀 2755·2019-08-28 18:05
閱讀 2332·2019-08-26 13:55