Angular 2组件:如何处理循环输入和输出
现在的情况:
我有一个父组件和一个子组件. 父级使用@Input初始化子级数据.当用户使用@Output编辑数据时,孩子会通知父母.并且因为数据是不可变的,所以孩子必须与该通知一起发送数据. 当父母得到通知时,它将检查提交的数据是否有效,然后将其设置(这也将新值传播到其他一些子组件). 问题: 在父项中设置新数据时,它当然也会将其提供给刚刚提交数据的子组件.这将触发孩子的ngOnChanges,然后触发UI的重绘. 一些背景: 父有几个不同的子组件,它们都依赖于相同的myItem数据,可以编辑这些数据,然后在更改时通知父级. 这是代码的简化版本,应该显示问题. 父组件: template: <child [input]="myItem" (output)="onMyItemChange($event)"> code: ngOnInit() { this.myItem = getDataViaHTTP(); } onMyItemChange($event) { if($event.myItem.isValid()) { this.myItem = $event.myItem; } } 子组件: 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()) } 如您所见,子组件从@Input获取数据并使其可变.在将其发送回父级之前,它将使其再次变为不可变. 是否有任何模式可以阻止这些循环事件?
如果我们坚持使用bi-directionalaly事件触发器,我想不出一种打破圆圈的方法.特别是有多个孩子.
方法1 我能想到的一种方式是父母和孩子都使用共享数据服务.数据一劳永逸地变化,因为所有各方都在使用相同的数据. globaldata.service.ts import { Injectable } from '@angular/core'; interface ShareObj { [id: string]: any; } @Injectable() export class GlobalDataService { shareObj: ShareObj = {}; } app.module.ts(假设这是你的根模块) import { GlobalDataService } from './globaldata.service'; // // skip .. // @NgModule({ // // skip .. // provider:[GlobalDataService] }) export class AppModule {} 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'; } child.component.ts template: <input [(ngModel)]="gd.shareObj[parent]"> code: import { GlobalDataService } from './globaldata.service'; // // skip .. // constructor(private gd: GlobalDataService){} @Input() parent; 方法2 – 广播队列 使用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); } } } 儿童 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,msg: this.myItem // send the whole object }; // Publish to queue name = parent id this.smq.publish(parent,lets do something this.myItem = m.msg; // Update local data console.log(m.Id + ' received: ' + m.msg); } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |