我正在寻找Angular5中$broadcast
和$on
的类似实现。我发现,我们可以创建自定义服务,使用broadcaster
进行此作业。
我有两个平行组件。我想听变更事件。每当父触发事件时,这两个组件应聆听并进行一些处理。但是我正在尝试这种方法,但是,要么只有一个Component1
或Component2
聆听事件。
broadcaster.ts
interface BroadcastEvent {
key: any;
data?: any;
}
@Injectable()
export class Broadcaster {
private _eventBus: Subject<BroadcastEvent>;
constructor() {
this._eventBus = new Subject<BroadcastEvent>();
}
broadcast(key: any, data?: any) {
this._eventBus.next({key, data});
}
on<T>(key: any): Observable<T> {
return this._eventBus.asObservable()
.filter(event => event.key === key)
.map(event => <T>event.data);
}
}
component1.ts
@Component({
selector: 'app-Component1',
templateUrl: './Component1.component.html',
styleUrls: ['./Component1.component.css']
})
export class Component1 implements OnInit{
@Input() data: Student;
constructor(private broadcaster: Broadcaster) {
}
ngOnInit() {
this.broadcaster.on<string>('selectStudent').subscribe(data => {
console.log("Component 1");
});
}
component2.ts
@Component({
selector: 'app-Component2',
templateUrl: './Component2.component.html',
styleUrls: ['./Component2.component.css']
})
export class Component2 implements OnInit{
@Input() data: Student;
constructor(private broadcaster: Broadcaster) {
}
ngOnInit() {
this.broadcaster.on<string>('selectStudent').subscribe(data => {
console.log("Component 2");
});
}
父级
@Component({
selector: 'app-Component1',
templateUrl: './Parent .component.html',
styleUrls: ['./Parent .component.css']
})
export class Parent implements OnInit{
data: Student;
constructor(private broadcaster: Broadcaster) {
}
ngOnInit() {
}
onClick(data) {
this.data = data;
this.broadcaster.broadcast('selectStudent');
console.log("Parent Component");
}
父html
<app-Component1 [data]="data"> </app-Component1>
<app-Component2 [data]="data"> </app-Component2>
输出
Parent Component
Component 1
输出
Parent Component
Component 2
我缺少什么吗?为什么所有组件都不听的事件?
实际上是一个更好的模式。如果component1
和component2
都是parent
组件的孩子,则应在两个孩子中实现ngOnChanges
。
ngonchanges
当Angular(RE(设置数据结合输入属性时。该方法接收当前和先前属性值的简单对象。 在ngoninit((和一个或多个数据结合的输入属性发生变化之前调用。
component1.ts
@Component({selector: 'comp1', template: `...`})
class Component1 implements OnChanges {
@Input()
data: any;
ngOnChanges(changes: SimpleChanges) {
const dataChange = changes['data'];
if (dataChange) {
// do something with the updated data
}
}
}
parent.ts
@Component({
selector: 'parent',
template: `
<comp1 [data]="data"></comp1>
<comp2 [data]="data"></comp2>
})
class Component1 implements OnChanges {
data: any;
onClick() {
// if you change the data here it will trigger
// ngOnChanges in the child components
}
}
我找到了Angular网站给出的方式。为广播活动写一项服务并收听活动。
datachangedservice.ts
@Injectable()
export class DataChangedService {
private dataChange = new Subject<Student>();
dataChanged$ = this.dataChange.asObservable();
dataChanged(data) {
this.dataChange.next(data);
}
}
component1.ts
@Component({
selector: 'app-Component1',
templateUrl: './Component1.component.html',
styleUrls: ['./Component1.component.css']
})
export class Component1 implements OnInit{
@Input() data: Student;
constructor(private broadcaster: DataChangedService) {
}
ngOnInit() {
this.broadcaster.dataChanged$.subscribe( data => {
// some code
});
}
parent.ts
@Component({
selector: 'app-Component1',
templateUrl: './Parent .component.html',
styleUrls: ['./Parent .component.css']
})
export class Parent implements OnInit{
data: Student;
constructor(private broadcaster: DataChangedService) {
}
ngOnInit() {
}
onClick(data) {
this.broadcaster.dataChanged(data);
console.log("Parent Component");
}