在 Angular 中是否没有等同于 $scope.emit()
或 $scope.broadcast()
的东西?
我知道 EventEmitter
功能,但据我所知,它只会向父 HTML 元素发出一个事件。
如果我需要在fx之间进行通信怎么办。 sibling 或 DOM 根中的组件与嵌套多层的元素之间?
最佳答案
AngularJS 中没有等同于 $scope.emit()
或 $scope.broadcast()
的东西。
组件内部的 EventEmitter 接近,但正如您提到的,它只会向直接父组件发出事件。
在 Angular 中,还有其他替代方案,我将在下面尝试解释。
@Input() 绑定(bind)允许应用程序模型连接到有向对象图中(根到叶)。组件的更改检测器策略的默认行为是将所有更改传播到来自任何连接组件的所有绑定(bind)的应用程序模型。
旁白:有两种类型的模型: View 模型和应用程序模型。应用程序模型通过@Input() 绑定(bind)连接。 View 模型只是一个绑定(bind)在组件模板中的组件属性(未使用 @Input() 修饰)。
回答您的问题:
如果我需要在同级组件之间进行通信怎么办?
共享应用模型: sibling 可以通过共享应用程序模型进行通信(就像 Angular 1)。例如,当一个兄弟对模型进行更改时,绑定(bind)到同一模型的另一个兄弟会自动更新。
组件事件:子组件可以使用@Output() 绑定(bind)向父组件发出事件。父组件可以处理事件,并操纵应用程序模型或它自己的 View 模型。对应用程序模型的更改会自动传播到直接或间接绑定(bind)到同一模型的所有组件。
服务事件:组件可以订阅服务事件。例如,两个兄弟组件可以订阅同一个服务事件并通过修改各自的模型来响应。更多内容见下文。
如何在 Root 组件和嵌套多层的组件之间进行通信?
- 共享应用程序模型:应用程序模型可以通过@Input() 绑定(bind)从根组件向下传递到深层嵌套的子组件。任何组件对模型的更改都会自动传播到共享同一模型的所有组件。
- 服务事件:您还可以将 EventEmitter 移动到共享服务,这允许任何组件注入(inject)服务并订阅事件。这样,Root 组件可以调用服务方法(通常是改变模型),该方法又会发出一个事件。往下几层,孙组件也注入(inject)了服务并订阅了相同的事件,可以处理它。任何更改共享应用程序模型的事件处理程序都将自动传播到依赖它的所有组件。这可能与 Angular 1 中的
$scope.broadcast()
最接近。下一节将更详细地描述这个想法。
使用服务事件传播变化的可观察服务示例
这是一个使用服务事件传播变化的可观察服务示例。添加 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));
}
}
关于angular - Angular 中的全局事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34700438/