没有相当于$scope.emit()$scope.broadcast()的Angular 吗?

我知道EventEmitter功能,但据我所知,它只会向父HTML元素发出一个事件.

如果我需要在fx之间沟通怎么办.DOM根中的一个组件和嵌套了几层的元素之间是同级还是同级?

推荐答案

来自AngularJS的值不等于$scope.emit()$scope.broadcast(). 组件内部的EventEmitter非常接近,但正如您所提到的,它只会向直接父组件发出事件.

在Angular中,我将try 在下面解释其他替代方案.

@Input()绑定允许应用程序模型在有向对象图(从根到叶)中连接.组件的变更检测器策略的默认行为是将所有变更传播到应用程序模型中,用于任何连接组件的所有绑定.

旁白:有两种类型的模型:视图模型和应用程序模型.应用程序模型通过@input()绑定连接.视图模型只是一个组件属性(没有用@input()修饰),它绑定在组件的模板中.

要回答您的问题:

如果我需要在同级组件之间通信呢?

  1. Shared Application Model: sibling 可以通过共享的应用程序模型进行通信(就像Angular 1一样).例如,当一个同级对模型进行更改时,绑定到同一模型的另一个同级将自动更新.

  2. Component Events:子组件可以使用@Output()绑定向父组件发送事件.父组件可以处理事件,并操纵应用程序模型或它自己的视图模型.对应用程序模型的更改会自动传播到直接或间接绑定到同一模型的所有组件.

  3. Service Events:组件可以订阅服务事件.例如,两个sibling 组件可以订阅相同的服务事件,并通过修改它们各自的模型来响应.下面是关于这一点的更多信息.

如何在根组件和多层嵌套的组件之间进行通信?

  1. Shared Application Model:应用程序模型可以通过@input()绑定从根组件向下传递到嵌套很深的子组件.从任何组件对模型所做的更改将自动传播到共享同一模型的所有组件.
  2. Service Events:您还可以将EventEmitter移动到共享服务,该服务允许任何组件注入服务并订阅事件.这样,根组件就可以调用服务方法(通常是改变模型),而服务方法又会发出一个事件.再往下几层,一个grand child组件也注入了服务并订阅了同一事件,可以处理它.任何更改共享应用程序模型的事件处理程序都将自动传播到依赖它的所有组件.这可能是距离角1最近的$scope.broadcast().下一节将更详细地描述这个 idea .

Example of an Observable Service that uses Service Events to Propagate Changes

下面是一个使用服务事件传播更改的可观察服务的示例.添加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));
    }
}

参考:Change Detection in Angular

Angular相关问答推荐

如何将CDkDropList与Angular FormArray和FormGroup一起使用?

Angular:浏览器中未显示一些Google Content图标

具有多重签名的Angular Mocking Service

具有多个输入的Angular struct 指令在第一次加载构件时没有值

如何使用独立组件在ANGLE(16+)中实现嵌套布线

使用`UrlHandlingStrategy`更改位置

如何将参数传递给Angular 服务

如何让 ag-Grid 事件读取私有方法?

根据环境变量动态加载Angular templateUrl

Angular 升级后 RXJS SwitchMap 无法与解析器一起正常工作

如何使用指令以Angular 传递默认值

如何在插值中编写条件?

设置 Angular Material Tooltip 的字体大小

无法从模块it was neither declared nor imported导出服务

如何为 Angular 2 中的渲染元素绑定事件监听器?

如何在 ngFor angular 2 内部使用 track

angular2中的httpinterceptor类似功能是什么?

Mat-autocomplete - 如何访问选定的选项?

在Angular2 Dart中设置路由和RouterLink的正确方法是什么

CustomPipe 没有提供者