本文介绍的内容是组件通信的常用方式:@Input、@Output、@ViewChild、模板变量、MessageService、Broadcaster (Angular 1.x $rootScope 中 $on、$broadcast ) 和 Pub - Sub 模式、RxJS Subject 存在的问题。
输入属性 (父组件 -> 子组件)
counter.component.ts
------ - ---------- ----- - ---- ---------------- ------------ --------- -------------- --------- - ------- -- ----- ------ ------- ---------------------- - --------- ------- ---------------------- - --------- - -- ------ ----- ---------------- - -------- ------ ------ - -- ----------- - ------------- - ----------- - ------------- - -
app.component.ts
------ - --------- - ---- ---------------- ------------ --------- ---------- --------- - ------------ ------------------------ - -- ------ ----- ------------ - ------------- ------ - -- -
输出属性 (子组件 -> 父组件)
counter.component.ts
------ - ---------- ------ ------- ------------ - ---- ---------------- ------------ --------- -------------- --------- - ------- -- ----- ------ ------- ---------------------- - --------- ------- ---------------------- - --------- - -- ------ ----- ---------------- - -------- ------ ------ - -- --------- ------- -------------------- - --- ----------------------- ----------- - ------------- ----------------------------- - ----------- - ------------- ----------------------------- - -
app.component.ts
------ - --------- - ---- ---------------- ------------ --------- ---------- --------- - -------------------- ------------ ---------------------- -------------------------------- - -- ------ ----- ------------ - ------------- ------ - -- ---------- ------- ------------------ ------- - -------------- - --------------------- ---------- - -
模板变量
child.component.ts
------ ----------- ---- ---------------- ------------ --------- ------------------ --------- ---- -- ---- --- -- ------ ----- -------------- - ------ ----- ------- -
parent.component.ts
------ ----------- ------- ---- ---------------- ------ ---------------- ---- ----------------------- ------------ --------- ------------------- --------- - ---------------- ----------- ------- ------------------- - --------------------------- - -- ------ ----- --------------- ---------- ------ - ------- ---------- ------- ------------- - - ---------- - -------------- - ------------------ - -
@ViewChild 装饰器
child.component.ts
------ - ---------- ------ - ---- ---------------- ------------ --------- ------------ --------- - -------- ------------- - -- ------ ----- -------------- - ----- ------ - --- -
app.component.ts
------ - ---------- ---------- ------------- - ---- ---------------- ------ - -------------- - ---- -------------------- ------------ --------- --------- --------- - ----------- -- ------- ---------- ------------ -- -- ------ ----- ------------ - -------------------------- --------- --------------- ----------------- - ------------------ - ------------------ - -
使用 MessageService - 基于 RxJS Subject
message.service.ts
------ - ---------- - ---- ---------------- ------ ------------ ---- ------------------ ------ - ------- - ---- --------------- ------------- ------ ----- -------------- - ------- ------- - --- --------------- -------------------- ------- - ------------------- ----- ------- --- - -------------- - -------------------- - ------------- --------------- - ------ ---------------------------- - -
home.component.ts
------ - --------- - ---- ---------------- ------ - -------------- - ---- -------------------- ------------ --------- ----------- --------- - ----- ------------- ------- ---------------------------- ---------------- ------- ------------------------------ ---------------- ------- -- ------ ----- ------------- - ------------------- --------------- --------------- -- -------------- ---- - ---------------------------------------- ---- ---- --------- -- --- ------------- - --------------- ---- - ----------------------------------- - -
app.component.ts
------ - ---------- --------- - ---- ---------------- ------ - ------------ - ---- -------------------- ------ - -------------- - ---- -------------------- ------------ --------- --------- --------- - ----- ---- -------------------------------------- ----------- ------ - -- ------ ----- ------------ ---------- --------- - -------- ---- ------------- ------------- ------------------- --------------- --------------- - ----------------- - ------------------- ------------------------ ------- -- - ------------ - -------- --- - ------------- - -------------------------------- - -
使用 Broadcaster - 基于 RxJS Subject
实现 Angular 1.x 中的 $rootScope 对象中 $on
和 $broadcast
的功能。
broadcaster.ts
------ - ---------- - ---- ---------------- ------ --------- ---- --------------- ------ ------------ ---- ------------------ ------ --------------------------- ------ ------------------------ --------- -------------- - ---- ---- ------ ---- - ------------- ------ ----- ----------- - ------- ---------- ------------------------ ------------- - -------------- - --- -------------------------- - -------------- ---- ------ ---- - ------------------------- ------- - ---------- ----- ------------- - ------ ----------------------------- ------------- -- --------- --- ---- ---------- -- --------------- - -
child.component.ts
------ - --------- - ---- ---------------- ------------ --------- ------- -- ------ ----- -------------- - ------------------- ------------ ------------ -- ------------------------- - -------------------------------------- ------------------ -- - --- --- - --------------------- - ------------------------------------- ----- ---------- - -
本文主要是介绍组件通讯的思路,提供的都是相对简单的示例。如果想深入了解,请参考 - angular.cn - component-communication。
我有话说
1.在实际开发中,我们也经常使用 Pub (发布) - Sub (订阅模式) 来实现模块之间的消息通讯。接下来我们看一下 Pub - Sub 的核心点:
- 至少包含 subscribe() 和 publish() 两个方法,subscribe() 用于实现消息订阅,publish() 方法用于发布消息。
- 支持订阅不同的消息类型,且对于任何一种消息类型都可以添加多个观察者。内部实现一般使用
key-value
结构进行消息类型和观察者列表的存储。 - 订阅观察者后,最好返回一个对象或函数对象,用于取消订阅。
具体示例如下(详细信息,请参考 - [Pub/Sub JavaScript Object](Pub/Sub JavaScript Object)):
--- ------ - ------------ --- ------ - --- --- --- - ---------------------- ------ - ---------- --------------- --------- - -- ---------------- -------------------- ------- ------------- - --- -- ---------- --- ----- - ---------------------------- --- -- ---------------- ------ - ------- ---------- - ------ --------------------- - -- -- -------- --------------- ----- - -------------------- ------- ------- ------------------------------------ - --------- -- --------- - ---- - ---- --- - -- -----
使用示例:
--- ------------ - ------------------------------ ------------- - -- ---- --- ---------------------------- - ---- ---------------- ---
2.RxJS Subject 在使用中存在一个问题,就是如果某个 observer (观察者) 在执行的时候出现异常,却没有进行异常处理,那么就会影响到其它的观察者。解决该问题,最简单的方式就是为所有的观察者添加异常处理。具体问题如下:
----- ------ - ----------------------------- ----- ------- - --- ------------- ----- ------- - ------------- -- - -- -- --- -- - ----- --- -------------- - ------ -- --- ------------------- -- ---------------- ---- ------------------- -- ---------------- ---- ------------------- -- ---------------- ---- --------------------------
以上代码运行后,控制台的输出结果:
- - - - - - - - ------------ -------- ------ ----
解决方案:
----- ------ - ----------------------------- ----- ------- - --- ------------- ----- ------- - ------------- -- - -- -- --- -- - ----- --- -------------- - ------ -- --- ------------------ - -- ---------------- --- ----- -- -------------- ------- - ------ -- ------------------ - -- ---------------- --- ----- -- -------------- ------- - ------ -- ------------------ - -- ---------------- --- ----- -- -------------- ------- - ------ -- --------------------------
关于 RxJS Subject 的详细信息,请查看 - RxJS Subject。