Ben*_*n M 8 immutability event-handling angular2-template angular
现在的情况:
我有一个parent
和一个child
组件.
在parent
初始化child
使用它的数据@Input
.child
当用户使用编辑数据时,通知父母@Output
.并且由于数据是不可变的,因此child
必须将数据与该通知一起发送.
当parent
得到通知时,它将检查提交的数据是否有效,然后将其设置(这也将新值传播到其他一些子组件).
问题:
当在其中设置新数据时parent
,它当然也会将其提供给child
刚刚提交数据的组件.这将触发child
's ngOnChanges
,然后触发重新绘制UI.
一些背景:
它parent
有几个不同的child
组件,它们都依赖于相同的myItem
数据,可以编辑这些数据,然后通知parent
更改.
这是代码的简化版本,应该会显示问题.
父组件:
template:
<child [input]="myItem" (output)="onMyItemChange($event)">
code:
ngOnInit() {
this.myItem = getDataViaHTTP();
}
onMyItemChange($event) {
if($event.myItem.isValid()) {
this.myItem = $event.myItem;
}
}
Run Code Online (Sandbox Code Playgroud)
子组件:
template:
<input [(ngModel)]="myItem.name" (ngModelChange)="modelChange($event)">
code:
@Input() input;
@Output() output = new EventEmitter();
myItem;
ngOnChanges(changes) {
this.myItem = changes.input.currentValue.toMutableJS();
}
modelChange($event) {
this.output.emit(this.myItem.toImmutableJS())
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,child
组件从中获取数据@Input
并使其可变.在将它发送回parent
它之前,它将再次变为不可变.
是否有任何模式可以阻止这些循环事件?
如果我们坚持使用bi-directionalaly事件触发器,我想不出一种打破圆圈的方法.特别是有多个孩子.
我能想到的一种方式是父母和孩子都使用共享数据服务.数据一劳永逸地变化,因为所有各方都在使用相同的数据.
globaldata.service.ts
import { Injectable } from '@angular/core';
interface ShareObj {
[id: string]: any;
}
@Injectable()
export class GlobalDataService {
shareObj: ShareObj = {};
}
Run Code Online (Sandbox Code Playgroud)
app.module.ts(假设这是你的根模块)
import { GlobalDataService } from './globaldata.service';
//
// skip ..
//
@NgModule({
//
// skip ..
//
provider:[GlobalDataService]
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
parent.component.ts(假设非root,多个实例,app.module的一部分)
template:
<child [parent]="myId"></child>
code:
import { GlobalDataService } from './globaldata.service';
//
// skip ..
//
// use uuid to generate unique id
private uuid = require('node-uuid');
myId = this.uuid.v1();
constructor(private gd: GlobalDataService){
// This can be string, array or object
this.gd.shareObj[myId]='data';
}
Run Code Online (Sandbox Code Playgroud)
child.component.ts
template:
<input [(ngModel)]="gd.shareObj[parent]">
code:
import { GlobalDataService } from './globaldata.service';
//
// skip ..
//
constructor(private gd: GlobalDataService){}
@Input() parent;
Run Code Online (Sandbox Code Playgroud)
使用RxJs主题订阅,如广播队列.我实际创建了一个包含示例的包:
https://github.com/J-Siu/ng2-simple-mq
https://github.com/J-Siu/ng2-simple-mq-example
想法:
父(假设非root,多个实例,app.module的一部分)
import {Component, OnInit} from '@angular/core';
import {SimpleMQ} from 'ng2-simple-mq';
template:
<child [parent]="myId"></child>
code:
export class SomeComponent implements OnInit {
title = 'Some Component';
// use uuid to generate unique id
private uuid = require('node-uuid');
myId = this.uuid.v1();
myItem = {};
constructor(private smq: SimpleMQ) { }
ngOnInit() {
this.smq.subscribe(this.myId, e => this.receiveBroadcast(e));
}
broadcast() {
let msg = {
id: this.myId,
msg: 'some messages or object go here'
};
// Publish to queue name 'this.myId'
this.smq.publish(this.myId, msg);
}
receiveBroadcast(m) {
if (m.id !== this.myId) {
// msg from soneone else, lets do something
this.myItem = m.msg; // Update local data
console.log(m.Id + ' received: ' + m.msg);
}
}
}
Run Code Online (Sandbox Code Playgroud)
儿童
import {Component, Input, OnInit} from '@angular/core';
import {SimpleMQ} from 'ng2-simple-mq';
template:
<input [(ngModel)]="myItem.name" (ngModelChange)="broadcast()">
code:
export class SomeComponent implements OnInit {
title = 'Some Component';
@Input() parent;
// use uuid to generate unique id
private uuid = require('node-uuid');
myId = this.uuid.v1();
myItem = {};
constructor(private smq: SimpleMQ) { }
ngOnInit() {
this.smq.subscribe(parent, e => this.receiveBroadcast(e));
}
broadcast() {
let msg = {
id: this.myId,
msg: this.myItem // send the whole object
};
// Publish to queue name = parent id
this.smq.publish(parent, msg);
}
receiveBroadcast(m) {
if (m.id !== this.myId) {
// msg from soneone else, lets do something
this.myItem = m.msg; // Update local data
console.log(m.Id + ' received: ' + m.msg);
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2443 次 |
最近记录: |