我知道EventEmitter功能,但据我所知,只会发出一个事件到父HTML元素。
如果我需要在fx之间通信怎么办?兄弟姐妹之间还是一个组件之间的根的DOM和一个元素嵌套几个级别深?
组件中的EventEmitter关闭,但是正如你所提到的,它只会向直接父组件发出一个事件。
在Angular 2中,还有其他替代方法,我将在下面解释。
@Input()绑定允许应用程序模型在有向对象图(根到叶)中连接。组件的变化检测器策略的默认行为是将来自任何连接组件的所有绑定的所有更改传播到应用程序模型。
旁白:有两种类型的模型:视图模型和应用程序模型。应用程序模型通过@Input()绑定连接。视图模型是一个只是一个组件属性(不用@Input()装饰,它绑定在组件的模板中。
回答你的问题:
如果我需要在兄弟元件之间通信怎么办?
>共享应用程序模型:
兄弟姐妹可以通过共享应用程序模型进行通信(就像angular 1)。例如,当一个同级对模型进行更改时,将自动更新与同一模型绑定的另一个同级。
>组件事件:子组件可以使用@Output()绑定向父组件发出事件。父组件可以处理事件,并处理应用程序模型或它自己的视图模型。对应用程序模型的更改将自动传播到直接或间接绑定到同一模型的所有组件。
>服务事件:组件可以订阅服务事件。例如,两个同级组件可以订阅相同的服务事件,并通过修改它们各自的模型来响应。更多关于这一点下面。
如何在根组件和嵌套几个级别的组件之间进行通信?
>共享应用程序模型:应用程序模型可以通过@Input()绑定从根组件传递到深层嵌套的子组件。从任何组件对模型的更改将自动传播到共享相同模型的所有组件。
>服务事件:您还可以将EventEmitter移动到共享服务,这允许任何组件注入服务和订阅事件。这样,根组件可以调用服务方法(通常使模型变异),这反过来发射事件。几个层次,一个grand-child组件,也注入了服务和订阅相同的事件,可以处理它。更改共享应用程序模型的任何事件处理程序将自动传播到依赖它的所有组件。这可能是最接近等价于$ scope.broadcast()从Angular 1。下一节更详细地描述这个想法。
使用服务事件传播更改的可观察服务示例
以下是使用服务事件传播更改的observable服务的示例。添加TodoItem时,服务会发出通知其组件订阅者的事件。
export class TodoItem { constructor(public name: string,public done: boolean) { } } export class TodoService { public itemAdded$: EventEmitter<TodoItem>; private todoList: TodoItem[] = []; constructor() { this.itemAdded$ = new EventEmitter(); } public list(): TodoItem[] { return this.todoList; } public add(item: TodoItem): void { this.todoList.push(item); this.itemAdded$.emit(item); } }
下面是根组件如何订阅事件:
export class RootComponent { private addedItem: TodoItem; constructor(todoService: TodoService) { todoService.itemAdded$.subscribe(item => this.onItemAdded(item)); } private onItemAdded(item: TodoItem): void { // do something with added item this.addedItem = item; } }
嵌套几个级别的子组件将以相同的方式订阅事件:
export class GrandChildComponent { private addedItem: TodoItem; constructor(todoService: TodoService) { todoService.itemAdded$.subscribe(item => this.onItemAdded(item)); } private onItemAdded(item: TodoItem): void { // do something with added item this.addedItem = item; } }
这里是调用服务触发事件的组件(它可以驻留在组件树中的任何位置):
@Component({ selector: 'todo-list',template: ` <ul> <li *ngFor="#item of model"> {{ item.name }} </li> </ul> <br /> Add Item <input type="text" #txt /> <button (click)="add(txt.value); txt.value='';">Add</button> ` }) export class TriggeringComponent{ private model: TodoItem[]; constructor(private todoService: TodoService) { this.model = todoService.list(); } add(value: string) { this.todoService.add(new TodoItem(value,false)); } }