Angular 2组件:如何处理循环输入和输出

前端之家收集整理的这篇文章主要介绍了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

想法:

>父级和所有子级将订阅同一队列
>在向队列广播时包含发件人ID,如果您使用我的包,则可以使用订阅ID作为发件人ID,因为它是一个uuid.
>如果消息来自自己,回调将检查发件人ID并且不采取任何行动

父(假设非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);
        }
    }
}

猜你在找的Angularjs相关文章