有没有相当于$scope.emit()
或$scope.broadcast()
在角?
我知道EventEmitter
功能,但据我所知,它只会向父HTML元素发出一个事件.
如果我需要在fx之间进行通信怎么办?兄弟姐妹或DOM根目录中的一个组件和一个嵌套了几层深层的元素?
pix*_*its 376
没有等同于$scope.emit()
或$scope.broadcast()
来自AngularJS.组件内部的EventEmitter接近,但正如您所提到的,它只会向直接父组件发出一个事件.
在Angular中,还有其他替代方案,我将在下面解释.
@Input()绑定允许应用程序模型在有向对象图(根到叶)中连接.组件的更改检测器策略的默认行为是将所有更改传播到应用程序模型,以用于来自任何连接组件的所有绑定.
旁白:有两种类型的模型:视图模型和应用程序模型.应用程序模型通过@Input()绑定连接.视图模型只是一个组件属性(未使用@Input()修饰),它绑定在组件的模板中.
回答你的问题:
如果我需要在兄弟组件之间进行通信怎么办?
共享应用程序模型:兄弟姐妹可以通过共享应用程序模型进行通信(就像角度1一样).例如,当一个兄弟对模型进行更改时,另一个绑定到同一模型的兄弟会自动更新.
组件事件:子组件可以使用@Output()绑定向父组件发出事件.父组件可以处理事件,并操纵应用程序模型或它自己的视图模型.对应用程序模型的更改会自动传播到直接或间接绑定到同一模型的所有组件.
服务事件:组件可以订阅服务事件.例如,两个兄弟组件可以订阅相同的服务事件,并通过修改其各自的模型进行响应.更多关于此的信息.
如何在Root组件和嵌套多个级别的组件之间进行通信?
$scope.broadcast()
与Angular 1 最接近的等价物.下一节将更详细地描述这个想法.使用服务事件传播更改的可观察服务的示例
以下是使用服务事件传播更改的可观察服务的示例.添加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);
}
}
Run Code Online (Sandbox Code Playgroud)
以下是根组件订阅事件的方式:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
嵌套了几个级别的子组件将以相同的方式订阅该事件:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
以下是调用服务以触发事件的组件(它可以驻留在组件树中的任何位置):
@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));
}
}
Run Code Online (Sandbox Code Playgroud)
参考:角度变化检测
jim*_*974 49
以下代码作为使用共享服务处理事件的Angular 2中$ scope.emit()或$ scope.broadcast()的替换示例.
import {Injectable} from 'angular2/core';
import * as Rx from 'rxjs/Rx';
@Injectable()
export class EventsService {
constructor() {
this.listeners = {};
this.eventsSubject = new Rx.Subject();
this.events = Rx.Observable.from(this.eventsSubject);
this.events.subscribe(
({name, args}) => {
if (this.listeners[name]) {
for (let listener of this.listeners[name]) {
listener(...args);
}
}
});
}
on(name, listener) {
if (!this.listeners[name]) {
this.listeners[name] = [];
}
this.listeners[name].push(listener);
}
off(name, listener) {
this.listeners[name] = this.listeners[name].filter(x => x != listener);
}
broadcast(name, ...args) {
this.eventsSubject.next({
name,
args
});
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
广播:
function handleHttpError(error) {
this.eventsService.broadcast('http-error', error);
return ( Rx.Observable.throw(error) );
}
Run Code Online (Sandbox Code Playgroud)
监听器:
import {Inject, Injectable} from "angular2/core";
import {EventsService} from './events.service';
@Injectable()
export class HttpErrorHandler {
constructor(eventsService) {
this.eventsService = eventsService;
}
static get parameters() {
return [new Inject(EventsService)];
}
init() {
this.eventsService.on('http-error', function(error) {
console.group("HttpErrorHandler");
console.log(error.status, "status code detected.");
console.dir(error);
console.groupEnd();
});
}
}
Run Code Online (Sandbox Code Playgroud)
它可以支持多个参数:
this.eventsService.broadcast('something', "Am I a?", "Should be b", "C?");
this.eventsService.on('something', function (a, b, c) {
console.log(a, b, c);
});
Run Code Online (Sandbox Code Playgroud)
t.8*_*888 16
我正在使用包装rxjs的消息服务Subject
(TypeScript)
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/filter'
import 'rxjs/add/operator/map'
interface Message {
type: string;
payload: any;
}
type MessageCallback = (payload: any) => void;
@Injectable()
export class MessageService {
private handler = new Subject<Message>();
broadcast(type: string, payload: any) {
this.handler.next({ type, payload });
}
subscribe(type: string, callback: MessageCallback): Subscription {
return this.handler
.filter(message => message.type === type)
.map(message => message.payload)
.subscribe(callback);
}
}
Run Code Online (Sandbox Code Playgroud)
组件可以订阅和广播事件(发件人):
import { Component, OnDestroy } from '@angular/core'
import { MessageService } from './message.service'
import { Subscription } from 'rxjs/Subscription'
@Component({
selector: 'sender',
template: ...
})
export class SenderComponent implements OnDestroy {
private subscription: Subscription;
private messages = [];
private messageNum = 0;
private name = 'sender'
constructor(private messageService: MessageService) {
this.subscription = messageService.subscribe(this.name, (payload) => {
this.messages.push(payload);
});
}
send() {
let payload = {
text: `Message ${++this.messageNum}`,
respondEvent: this.name
}
this.messageService.broadcast('receiver', payload);
}
clear() {
this.messages = [];
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Run Code Online (Sandbox Code Playgroud)
(接收器)
import { Component, OnDestroy } from '@angular/core'
import { MessageService } from './message.service'
import { Subscription } from 'rxjs/Subscription'
@Component({
selector: 'receiver',
template: ...
})
export class ReceiverComponent implements OnDestroy {
private subscription: Subscription;
private messages = [];
constructor(private messageService: MessageService) {
this.subscription = messageService.subscribe('receiver', (payload) => {
this.messages.push(payload);
});
}
send(message: {text: string, respondEvent: string}) {
this.messageService.broadcast(message.respondEvent, message.text);
}
clear() {
this.messages = [];
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Run Code Online (Sandbox Code Playgroud)
返回一个rxjs 对象的subscribe
方法,可以取消订阅,如下所示:MessageService
Subscription
import { Subscription } from 'rxjs/Subscription';
...
export class SomeListener {
subscription: Subscription;
constructor(private messageService: MessageService) {
this.subscription = messageService.subscribe('someMessage', (payload) => {
console.log(payload);
this.subscription.unsubscribe();
});
}
}
Run Code Online (Sandbox Code Playgroud)
另请参阅此答案:https://stackoverflow.com/a/36782616/1861779
您可以使用EventEmitter或 observables创建您在DI中注册的eventbus服务.每个想要参与的组件只是将服务作为构造函数参数请求并发出和/或订阅事件.
也可以看看
归档时间: |
|
查看次数: |
122416 次 |
最近记录: |