角度2组件:如何处理循环输入和输出 [英] Angular 2 Components: How to handle circular Inputs and Outputs

查看:142
本文介绍了角度2组件:如何处理循环输入和输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前情况

我有一个 child 组件。

初始化 child 的数据使用其 @Input 。而用户使用 @Output 编辑数据时, child 通知父级。而且由于数据是不可变的小孩必须随同通知一起发送数据。

The parent initializes the child's data using its @Input. And the child notifies the parent, when the user edited the data using the @Output. And because the data is immutable, the child has to send the data along with that notification.

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

When the parent got notified, it will check if the submitted data is valid, and then will set it (this will propagate the new value to some other child components as well).

问题:

将新数据设置在,当然也会将它提供给刚提交数据的组件。这将触发孩子 ngOnChanges ,然后触发UI的重绘。

When setting the new data inside the parent, it will of course also give it to the child component which just submitted the data. This will trigger the child's ngOnChanges, which then triggers a repaint of the UI.

某些背景

几个不同的组件,这些组件都依赖于相同的 myItem 数据,可以编辑此数据,然后通知 parent 更改。

The parent has several different child components, which all rely on the same myItem data and can edit this data and then notify the parent on change.

这是代码的简化版本,应该出现问题。

Here's a simplified version of the code, that should show up the problem.

父组件

template:
    <child [input]="myItem" (output)="onMyItemChange($event)">

code:
    ngOnInit() {
        this.myItem = getDataViaHTTP();
    }

    onMyItemChange($event) {
        if($event.myItem.isValid()) {
            this.myItem = $event.myItem;
        }
    }

子组件 / p>

Child Component:

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 获取数据,并使其变为可变。在发送回父母之前,它将使其不可变。


As you can see, the child component takes the data from the @Input and makes it mutable. And before sending it back to the parent it will make it immutable again.

是否有任何模式来阻止这些循环事件?

Is there any pattern to prevent these circular events?

推荐答案

我不能想到打破如果我们坚持使用双向事件触发器,则离开圈子。特别是与多个孩子。

I can't think of a way to break the away from the circle if we stick with bi-directionaly event trigger. Especially with multiple children.

我可以想到的一个方法是父母和孩子都使用共享数据服务。数据是一次性改变,因为所有各方都使用相同的数据。

One way I can think of is both parent and children use a share data service. Data is change once and for all, as all parties are using the same data.

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主题订阅,如广播队列。我实际上创建了一个包,例如:

Method 2 - broadcast queue

Use RxJs subject subscription, like a broadcast queue. I have actually created a package with example:

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

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

想法:


  1. 父母和所有孩子都将订阅同一个队列

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

来自'@ angular / core'的

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

这篇关于角度2组件:如何处理循环输入和输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆