最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Angular組件間通信的新解決方案詳解

 更新時(shí)間:2023年08月15日 14:28:35   作者:OpenTiny社區(qū)  
本文通過對(duì)比幾種Angular組件間的通信方式,給大家介紹了一種新的Angular組件間通信的解決方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

其中首創(chuàng)了公共的dataService,用于任意組件間通信。 dataService通過angular service特性和注冊(cè)表的使用,可以實(shí)現(xiàn)消息的一收一發(fā),無需再寫單獨(dú)的service邏輯。

背景

一般來講,Angular 已有的組件間通信方式有哪些?

序號(hào)通信方式描述
1輸入屬性(@Input)通過屬性綁定,將數(shù)據(jù)從父組件傳遞給子組件。
2輸出屬性(@Output)通過事件綁定,子組件可以發(fā)送事件給父組件,并傳遞數(shù)據(jù)。
3父子組件直接訪問在某些情況下,父組件可以通過 ViewChild 或 ContentChild 裝飾器直接訪問子組件或模板中的元素。
4服務(wù)(Service)創(chuàng)建共享的服務(wù),組件可以注入該服務(wù)來存儲(chǔ)和獲取數(shù)據(jù)。
5RxJS Subject 和 Observable使用 RxJS 中的 Subject 和 Observable 來實(shí)現(xiàn)組件之間的消息傳遞。
6Angular 路由參數(shù)通過路由參數(shù)在不同組件之間傳遞數(shù)據(jù)。
7NgRx使用 NgRx 狀態(tài)管理庫來實(shí)現(xiàn)更復(fù)雜的組件間通信和數(shù)據(jù)共享。

但以上方法各有局限性,要么代碼繁多,要么學(xué)習(xí)成本高,尤其是跨越多個(gè)組件的通信,例如下圖中從組件D組件G,用前兩種方式就太繁瑣了,方式 4 和 5 可能是常用解決方案,但是仍然有些繁瑣——需要為每一組消息傳遞寫專有的 service 代碼

組件A
???????/??????\
?????組件B??????組件C
????/???\??????/????\
??組件D?組件E?組件F??組件G

本文介紹的通信方式是在方式 4 和 5 的基礎(chǔ)上,進(jìn)行了做了特殊的抽象處理,實(shí)現(xiàn)了一個(gè)公共的 dataService,最終實(shí)現(xiàn)了消息一收一發(fā),無需再寫中間環(huán)節(jié)的代碼。

常規(guī)方式實(shí)現(xiàn)組件間消息通信

為了做對(duì)比,這里先介紹一下前文所示的方式4+5方案,這個(gè)方案通過 service 和 rxjs 的 subject 結(jié)合使用,實(shí)現(xiàn)任意組件間通信。

首先,我們創(chuàng)建一個(gè)名為MessageService的服務(wù),用于在組件之間傳遞消息:

//?message.service.ts
import?{?Injectable?}?from?'@angular/core';
import?{?Subject?}?from?'rxjs';
@Injectable({
??providedIn:?'root',
})
export?class?MessageService?{
??private?messageSubject?=?new?Subject<string>();
??//?Observable?string?stream
??message$?=?this.messageSubject.asObservable();
??//?Service?method?to?send?a?message
??sendMessage(message:?string)?{
????this.messageSubject.next(message);
??}
}

接下來,我們有兩個(gè)組件,SenderComponentReceiverComponentSenderComponent用于發(fā)送消息,而ReceiverComponent用于接收消息。

//?sender.component.ts
import?{?Component?}?from?'@angular/core';
import?{?MessageService?}?from?'./message.service';
@Component({
??selector:?'app-sender',
??template:?`
????<input?type="text"?[(ngModel)]="message"?/>
????<button?(click)="sendMessage()">發(fā)送消息</button>
??`,
})
export?class?SenderComponent?{
??message:?string;
??constructor(private?messageService:?MessageService)?{}
??sendMessage()?{
????this.messageService.sendMessage(this.message);
????this.message?=?'';?//?清空輸入框
??}
}
//?receiver.component.ts
import?{?Component?}?from?'@angular/core';
import?{?MessageService?}?from?'./message.service';
@Component({
??selector:?'app-receiver',
??template:?`?<div>接收到的消息:?{{?receivedMessage?}}</div>?`,
})
export?class?ReceiverComponent?{
??receivedMessage:?string;
??constructor(private?messageService:?MessageService)?{
????this.messageService.message$.subscribe(message?=>?{
??????this.receivedMessage?=?message;
????});
??}
}

在這個(gè)示例中,我們通過MessageService來實(shí)現(xiàn)了SenderComponentReceiverComponent發(fā)送消息的功能。MessageService中使用了 RxJS 的Subject來創(chuàng)建一個(gè)可觀察的消息流,然后在SenderComponent中調(diào)用sendMessage方法來發(fā)送消息,而在ReceiverComponent中使用subscribe來訂閱消息流并接收消息。

請(qǐng)注意,為了使MessageService成為全局可用的單例服務(wù),我們?cè)?code>@Injectable裝飾器中設(shè)置了providedIn: 'root'。這樣一來,MessageService將成為整個(gè)應(yīng)用程序中所有組件共享的單一實(shí)例。

為了使示例正常工作,別忘了將SenderComponentReceiverComponent添加到所屬的模塊中,并在模塊的模板中放置對(duì)應(yīng)的組件選擇器。

這樣,SenderComponent發(fā)送的消息將通過MessageService傳遞給ReceiverComponent,并顯示在ReceiverComponent中。這就完成了通過 Service 和 RxJS 的 Subject 實(shí)現(xiàn)組件間消息通信的示例。

新的解決方案

理解本方案,默認(rèn)需要熟悉 Angular 的 service 存儲(chǔ)傳遞數(shù)據(jù)原理 和 rxjs 的多播用法。

本方案原理是,通過 service 單例的特性(service 在模塊內(nèi)組件間是共享的)和 Subject 的多播特性,實(shí)現(xiàn)一個(gè)公共的 service,通過公共的 service 實(shí)現(xiàn)數(shù)據(jù)傳遞。相對(duì)的,如同前文中的message.service.ts文件所示,開發(fā)者需要為每一組通信單獨(dú)創(chuàng)建 service 文件,單獨(dú)寫響應(yīng)的邏輯。

理解本方案的三個(gè)關(guān)鍵點(diǎn):

單例 通過在@Injectable裝飾器中設(shè)置providedIn: 'root',service 成為整個(gè)應(yīng)用程序中所有組件共享的單一實(shí)例。因?yàn)槭枪蚕淼?,所以能作為通信中消息的載體。這是本方案的根本前提。

rxjs 的多播 基礎(chǔ)原理是觀察者模式(即發(fā)布訂閱模式)

注冊(cè)表 為了復(fù)用 service,簡化代碼,本方案引入了一個(gè)注冊(cè)表,用來存儲(chǔ)對(duì)應(yīng)每個(gè)消息事件的 Subject 對(duì)象。Subject 對(duì)象在創(chuàng)建監(jiān)聽時(shí)(需要接收消息的地方)創(chuàng)建。

service 代碼如下:

//?dataService.service.ts
import?{?Injectable?}?from?'@angular/core';
import?{?Subject,?Subscription?}?from?'rxjs';
@Injectable({
??providedIn:?'root',
})
export?class?DataService<T>?{
??//?創(chuàng)建注冊(cè)表,用于存放監(jiān)聽器
??private?events?=?new?Map();
??/**
???*?發(fā)送消息
???*
???*?@param?{string}?event?事件。用于區(qū)別不同的監(jiān)聽
???*?@param?{T}?value?消息內(nèi)容
???*?@returns?{void}
???*?@memberof?DataService
???*/
??sendMessage(event:?string,?value:?T):?void?{
????if?(!this.events.has(event))?{
??????return;
????}
????this.events.get(event).subject.next(value);
??}
??/**
???*?獲取監(jiān)聽器
???*
???*?監(jiān)聽器其實(shí)就是一個(gè)rxjs?Subject對(duì)象,通過訂閱來獲取數(shù)據(jù)。
???*
???*?注意:
???*?1.getListener()應(yīng)該在sendMessage()之前,否則sendMessage()中獲取不到監(jiān)聽器,無法發(fā)消息
???*?2.getListener()應(yīng)放在ngOnInit()、ngAfterViewInit()等只會(huì)執(zhí)行一次的生命周期函數(shù)中
???*
???*?@param?{string}?event?事件。用于區(qū)別不同的監(jiān)聽
???*?@returns?{Subject<T>}
???*?@memberof?DataService
???*/
??getListener(event:?string):?Subject<T>?{
????//?多處監(jiān)聽時(shí)會(huì)走到此分支
????if?(this.events.has(event))?{
??????const?current?=?this.events.get(event);
??????current.count++;
??????return?current.subject;
????}
????const?listener?=?{
??????count:?1,?//?該字段用于記錄監(jiān)聽(訂閱)者個(gè)數(shù)
??????subject:?new?Subject<T>(),
????};
????/**
?????*?創(chuàng)建監(jiān)聽器,并將其加入注冊(cè)表
?????*
?????*?所在函數(shù)在創(chuàng)建監(jiān)聽(訂閱)時(shí)調(diào)用,監(jiān)聽發(fā)生在發(fā)送消息之前,所以在監(jiān)聽這里將監(jiān)聽器加入注冊(cè)表
?????*/
????this.events.set(event,?listener);
????return?listener.subject;
??}
??/**
???*?取消訂閱
???*
???*?必須手動(dòng)取消訂閱。
???*?取消時(shí)檢查監(jiān)聽者個(gè)數(shù)。如果沒有監(jiān)聽者了,就移除監(jiān)聽器。
???*
???*?@param?{string}?event
???*?@param?{Subscription}?subscription
???*?@returns
???*?@memberof?DataService
???*/
??cancelSubscription(event:?string,?subscription:?Subscription)?{
????if?(!this.events.has(event))?{
??????return;
????}
????const?current?=?this.events.get(event);
????current.count--;
????if?(current.count?===?0)?{
??????//?沒有監(jiān)聽者了,就移除監(jiān)聽器
??????this.events.delete(event);
????}
????subscription.unsubscribe();
??}
}

使用時(shí)只需引入上面的公共 dataService,然后以如下示例的方式直接調(diào)用 api 就行。

創(chuàng)建監(jiān)聽的示例:

//?接收傳遞過來的消息
??receiveChangeMessage;
??ngOnInit()?{
????...
????this.subscription?=?this.dataService.getListener('event_name').subscribe(message?=>?{
????????this.receiveChangeMessage?=?message;
??????});
????...
??}
??ngOnDestroy()?{
????this.dataService.cancelSubscription('event_name',?this.subscription);
??}

發(fā)送消息的示例:

public?onSomethingChange(value:?boolean):?void?{

????...

????this.dataService.sendMessage('event_name',?value);
??}

給出一個(gè)較完整的使用示例

以下是一個(gè)使用上文提供的DataService實(shí)現(xiàn)組件間消息通信的示例:

假設(shè)我們有兩個(gè)組件:SenderComponentReceiverComponent,它們需要通過DataService來傳遞消息。

//?sender.component.ts
import?{?Component?}?from?'@angular/core';
import?{?DataService?}?from?'./data.service';
@Component({
??selector:?'app-sender',
??template:?`
????<input?type="text"?[(ngModel)]="message"?/>
????<button?(click)="sendMessage()">發(fā)送消息</button>
??`,
})
export?class?SenderComponent?{
??message:?string;
??constructor(private?dataService:?DataService<string>)?{}
??sendMessage()?{
????this.dataService.sendMessage('customEvent',?this.message);
????this.message?=?'';?//?清空輸入框
??}
}
//?receiver.component.ts
import?{?Component,?OnInit,?OnDestroy?}?from?'@angular/core';
import?{?DataService?}?from?'./data.service';
import?{?Subscription?}?from?'rxjs';
@Component({
??selector:?'app-receiver',
??template:?`?<div>接收到的消息:?{{?receivedMessage?}}</div>?`,
})
export?class?ReceiverComponent?implements?OnInit,?OnDestroy?{
??receivedMessage:?string;
??subscription:?Subscription;
??constructor(private?dataService:?DataService<string>)?{}
??ngOnInit()?{
????this.subscription?=?this.dataService.getListener('customEvent').subscribe(message?=>?{
??????this.receivedMessage?=?message;
????});
??}
??ngOnDestroy()?{
????this.dataService.cancelSubscription('customEvent',?this.subscription);
??}
}

在這個(gè)示例中,我們通過DataService實(shí)現(xiàn)了SenderComponentReceiverComponent發(fā)送消息的功能。DataServicesendMessage方法用于發(fā)送消息,而getListener方法用于訂閱消息,并在接收到消息時(shí)更新ReceiverComponent中的receivedMessage屬性。cancelSubscription方法用于取消訂閱,并在不再有監(jiān)聽者時(shí)從注冊(cè)表中移除監(jiān)聽器。

請(qǐng)確保將SenderComponentReceiverComponent添加到所屬的模塊中,并在模塊的模板中放置對(duì)應(yīng)的組件選擇器。

通過使用DataService,SenderComponent發(fā)送的消息將傳遞給ReceiverComponent,并顯示在ReceiverComponent中。這樣,我們成功地實(shí)現(xiàn)了組件間消息通信。

實(shí)踐拓展

后續(xù)可以做成插件,以裝飾器的形式調(diào)用。

export?class?ReceiveComponent?{
??@listen('messageEvent')
??message;
}

export?class?SendComponent?{
??@send('messageEvent')
??message;
}

以上就是 屈金雄 同學(xué)的分享,如果你也有更多前端技術(shù)想與我們交流,歡迎投稿。除此之外,也歡迎你參與到 OpenTiny 開源中來??,一起共建項(xiàng)目,一起研討前端技術(shù)。

關(guān)于 OpenTiny

OpenTiny 是一套企業(yè)級(jí)組件庫解決方案,適配 PC 端 / 移動(dòng)端等多端,涵蓋 Vue2 / Vue3 / Angular 多技術(shù)棧,擁有主題配置系統(tǒng) / 中后臺(tái)模板 / CLI 命令行等效率提升工具,可幫助開發(fā)者高效開發(fā) Web 應(yīng)用。

核心亮點(diǎn):

  • 跨端跨框架:使用 Renderless 無渲染組件設(shè)計(jì)架構(gòu),實(shí)現(xiàn)了一套代碼同時(shí)支持 Vue2 / Vue3,PC / Mobile 端,并支持函數(shù)級(jí)別的邏輯定制和全模板替換,靈活性好、二次開發(fā)能力強(qiáng)。
  • 組件豐富:PC 端有80+組件,移動(dòng)端有30+組件,包含高頻組件 Table、Tree、Select 等,內(nèi)置虛擬滾動(dòng),保證大數(shù)據(jù)場(chǎng)景下的流暢體驗(yàn),除了業(yè)界常見組件之外,我們還提供了一些獨(dú)有的特色組件,如:Split 面板分割器、IpAddress IP地址輸入框、Calendar 日歷、Crop 圖片裁切等
  • 配置式組件:組件支持模板式和配置式兩種使用方式,適合低代碼平臺(tái),目前團(tuán)隊(duì)已經(jīng)將 OpenTiny 集成到內(nèi)部的低代碼平臺(tái),針對(duì)低碼平臺(tái)做了大量優(yōu)化
  • 周邊生態(tài)齊全:提供了基于 Angular + TypeScript 的 TinyNG 組件庫,提供包含 10+ 實(shí)用功能、20+ 典型頁面的 TinyPro 中后臺(tái)模板,提供覆蓋前端開發(fā)全流程的 TinyCLI 工程化工具,提供強(qiáng)大的在線主題配置平臺(tái) TinyTheme

以上就是Angular組件間通信的新解決方案詳解的詳細(xì)內(nèi)容,更多關(guān)于Angular組件間通信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Angular2實(shí)現(xiàn)組件交互的方法分析

    Angular2實(shí)現(xiàn)組件交互的方法分析

    這篇文章主要介紹了Angular2實(shí)現(xiàn)組件交互的方法,結(jié)合實(shí)例形式總結(jié)分析了Angular2中組件交互的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2017-12-12
  • 學(xué)習(xí)Angularjs分頁指令

    學(xué)習(xí)Angularjs分頁指令

    這篇文章主要和大家一起學(xué)習(xí)Angularjs分頁指令,代碼很詳細(xì),文章結(jié)構(gòu)緊湊,感興趣的小伙伴們可以參考一下
    2016-07-07
  • AngularJS語法詳解(續(xù))

    AngularJS語法詳解(續(xù))

    本文續(xù)上文,接著介紹AngularJS語法,和上文一樣,都是通過示例來向大家分析說明,非常不錯(cuò)的一篇文章,推薦給大家。
    2015-01-01
  • 從源碼看angular/material2 中 dialog模塊的實(shí)現(xiàn)方法

    從源碼看angular/material2 中 dialog模塊的實(shí)現(xiàn)方法

    這篇文章主要介紹了 從源碼看angular/material2 中 dialog模塊的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2017-10-10
  • AngularJS 自定義指令詳解及示例代碼

    AngularJS 自定義指令詳解及示例代碼

    本文主要介紹AngularJS 自定義指令,這里整理了基礎(chǔ)資料及詳細(xì)的示例代碼及實(shí)現(xiàn)效果圖,有需要的小伙伴可以參考下
    2016-08-08
  • 對(duì)Angular.js Controller如何進(jìn)行單元測(cè)試

    對(duì)Angular.js Controller如何進(jìn)行單元測(cè)試

    這篇文章主要給大家介紹了如何對(duì)Angular Controller進(jìn)行單頁測(cè)試。如果你不太了解angular也沒關(guān)系,本文也會(huì)提及關(guān)于Angular的一些知識(shí)。文中通過示例代碼介紹的很詳細(xì),詳細(xì)對(duì)大家的理解和學(xué)習(xí)很有幫助,下面來一起看看吧。
    2016-10-10
  • 使用Angular CDK實(shí)現(xiàn)一個(gè)Service彈出Toast組件功能

    使用Angular CDK實(shí)現(xiàn)一個(gè)Service彈出Toast組件功能

    本文主要寫用cdk實(shí)現(xiàn)一個(gè)簡單的Toast組件,使用的是cdk中的overlay模塊,需要手動(dòng)安裝環(huán)境,具體安裝方法及相關(guān)實(shí)現(xiàn)代碼跟隨小編一起看看吧
    2021-07-07
  • Angularjs中的頁面訪問權(quán)限怎么設(shè)置

    Angularjs中的頁面訪問權(quán)限怎么設(shè)置

    最近一直在忙一個(gè)手機(jī)端的項(xiàng)目,所以對(duì)js學(xué)習(xí)有點(diǎn)松撤了。今天小編抽時(shí)間跟大家分享一篇關(guān)于angularjs中的頁面訪問權(quán)限設(shè)置教處,對(duì)angularjs訪問權(quán)限感興趣的朋友一起學(xué)習(xí)吧
    2016-11-11
  • 使用AngularJS創(chuàng)建自定義的過濾器的方法

    使用AngularJS創(chuàng)建自定義的過濾器的方法

    這篇文章主要介紹了使用AngularJS創(chuàng)建自定義的過濾器的方法,AngularJS是非常熱門的JavaScript庫,需要的朋友可以參考下
    2015-06-06
  • angular forEach方法遍歷源碼解讀

    angular forEach方法遍歷源碼解讀

    這篇文章主要為大家詳細(xì)了angular forEach方法遍歷源碼,forEach()方法用于遍歷對(duì)象或數(shù)組,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01

最新評(píng)論

铜川市| 大丰市| 调兵山市| 十堰市| 孟津县| 濮阳市| 梅河口市| 桓仁| 土默特左旗| 台前县| 巩义市| 咸丰县| 安义县| 轮台县| 潜江市| 仙桃市| 汝州市| 扶余县| 正安县| 蓝田县| 濮阳市| 潍坊市| 香河县| 高青县| 申扎县| 玉树县| 拜城县| 新营市| 仁寿县| 保山市| 临澧县| 桐柏县| 禹州市| 永寿县| 吉隆县| 蓬安县| 确山县| 黄山市| 祁东县| 曲松县| 宜兰市|