gpt4 book ai didi

Angular 2 组件 : How to handle circular Inputs and Outputs

转载 作者:太空狗 更新时间:2023-10-29 17:14:37 25 4
gpt4 key购买 nike

现状:

我有一个parent 和一个child 组件。

parent 使用其@Input 初始化child 的数据。当用户使用 @Output 编辑数据时,child 会通知父级。因为数据是不可变的child 必须连同通知一起发送数据。

parent 收到通知时,它将检查提交的数据是否有效,然后设置它(这会将新值传播到其他一些子组件)。

问题:

parent里面设置新数据的时候,当然也会把它给刚刚提交数据的child组件。这将触发 childngOnChanges,然后触发 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;
}
}

子组件:

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())
}

如您所见,child 组件从 @Input 获取数据并使其可变。在将其发送回 parent 之前,它将再次使其不可变。


是否有任何模式可以防止这些循环事件?

最佳答案

如果我们坚持使用双向事件触发器,我想不出一种方法来打破圆圈。尤其是有多个 child 。

方法一

我能想到的一种方法是 parent 和 child 都使用共享数据服务。数据是一劳永逸的,因为各方都在使用相同的数据。

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;

方法二——广播队列

使用 RxJs 主题订阅,就像广播队列一样。我实际上已经用示例创建了一个包:

https://github.com/J-Siu/ng2-simple-mq

https://github.com/J-Siu/ng2-simple-mq-example

想法:

  1. parent 和所有 child 将订阅同一个队列
  2. 在向队列广播时包含一个发送者 ID,如果您使用我的包,您可以使用订阅 ID 作为发送者 ID,因为它是一个 uuid。
  3. 回调将检查发件人 ID,如果消息来自自己则不执行任何操作

父级(假设非根,多个实例,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);
}
}
}

child

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);
}
}
}

关于 Angular 2 组件 : How to handle circular Inputs and Outputs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38920232/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com