your programing

Angular 2의 구성 요소간에 데이터를 어떻게 공유합니까?

lovepro 2020. 10. 12. 08:02
반응형

Angular 2의 구성 요소간에 데이터를 어떻게 공유합니까?


Angular 1.xx에서는 단순히 동일한 서비스를 요청하면 동일한 인스턴스로 끝나므로 서비스에서 데이터를 공유 할 수 있습니다.

이제 Angular 2에는 내 서비스에 대한 참조가있는 구성 요소가 있습니다. 나는 서비스의 데이터를 읽고 수정할 수 있습니다. 다른 구성 요소에 동일한 서비스를 삽입하려고하면 새 인스턴스를 얻는 것처럼 보입니다.

내가 도대체 ​​뭘 잘못하고있는 겁니까? 패턴 자체가 잘못된 것입니까 (서비스를 사용하여 데이터를 공유) 또는 서비스를 싱글 톤 (앱의 한 인스턴스 내) 또는 다른 것으로 표시해야합니까?

나는 2.0.0-alpha.27/btw에있다

주석의 appInjector(edit : now providers)를 통해 서비스를 주입 한 @Component다음 생성자에 참조를 저장합니다. 구성 요소에서 로컬로 작동합니다. 내가 생각했던 것처럼 구성 요소 간에는 작동하지 않습니다 (동일한 서비스 인스턴스를 공유하지 않음).

업데이트 : Angular 2.0.0부터는 @ngModule을 사용하여 해당 providers속성 아래에 서비스를 정의합니다 @ngModule. 그러면 해당 서비스의 동일한 인스턴스가 해당 모듈의 각 구성 요소, 서비스 등에 전달됩니다. https://angular.io/docs/ts/latest/guide/ngmodule.html#providers


서비스 싱글 톤은 좋은 솔루션입니다. 다른 방법- data/events bindings.

다음은 둘 다의 예입니다.

class BazService{
  n: number = 0;
  inc(){
    this.n++;
  }
}

@Component({
  selector: 'foo'
})
@View({
  template: `<button (click)="foobaz.inc()">Foo {{ foobaz.n }}</button>`
})
class FooComponent{
  constructor(foobaz: BazService){
    this.foobaz = foobaz;
  }
}

@Component({
  selector: 'bar',
  properties: ['prop']
})
@View({
  template: `<button (click)="barbaz.inc()">Bar {{ barbaz.n }}, Foo {{ prop.foobaz.n }}</button>`
})
class BarComponent{
  constructor(barbaz: BazService){
    this.barbaz = barbaz;
  }
}

@Component({
    selector: 'app',
    viewInjector: [BazService]
})
@View({
  template: `
    <foo #f></foo>
    <bar [prop]="f"></bar>
  `,
  directives: [FooComponent, BarComponent]
})
class AppComponent{}

bootstrap(AppComponent);

라이브 시청


@maufarinelli의 의견은 내가 볼 때까지 @Alexander Ermolov의 대답에도 불구 하고이 문제로 벽에 머리를 대고 있었기 때문에 자체 대답을 할 가치가 있습니다.

문제는 당신이를 추가 할 때 providers당신에게 component:

@Component({
    selector: 'my-selector',
    providers: [MyService],
    template: `<div>stuff</div>`
})

이로 인해 서비스의 새 인스턴스가 싱글 톤 이 아닌 주입 됩니다.

따라서을 providers: [MyService]제외하고 응용 프로그램에서 모든 인스턴스를 제거 module하면 작동합니다!


@Component 데코레이터의 입력과 출력을 사용해야합니다. 다음은 둘 다 사용하는 가장 기본적인 예입니다.

import { bootstrap } from 'angular2/platform/browser';
import { Component, EventEmitter } from 'angular2/core';
import { NgFor } from 'angular2/common';

@Component({
  selector: 'sub-component',
  inputs: ['items'],
  outputs: ['onItemSelected'],
  directives: [NgFor],
  template: `
    <div class="item" *ngFor="#item of items; #i = index">
      <span>{{ item }}</span>
      <button type="button" (click)="select(i)">Select</button>
    </div>
  `
})

class SubComponent {
  onItemSelected: EventEmitter<string>;
  items: string[];

  constructor() {
    this.onItemSelected = new EventEmitter();
  }

  select(i) {
    this.onItemSelected.emit(this.items[i]);
  }
}

@Component({
  selector: 'app',
  directives: [SubComponent],
  template: `
    <div>
      <sub-component [items]="items" (onItemSelected)="itemSelected($event)">
      </sub-component>
    </div>
  `
})

class App {
  items: string[];

  constructor() {
    this.items = ['item1', 'item2', 'item3'];
  }

  itemSelected(item: string): void {
    console.log('Selected item:', item);
  }
}

bootstrap(App);

상위 구성 요소 템플릿에서 :

<hero-child [hero]="hero">
</hero-child>

하위 구성 요소에서 :

@Input() hero: Hero;

출처 : https://angular.io/docs/ts/latest/cookbook/component-communication.html


There are many ways. This one is an example using propagation between parent and child elements. This is very efficient.

I submitted an example that permits to view the usage of two ways databinding within two forms. If somebody can provide a plunkr sample this would be very nice ;-)

You may look for another way using a service provider. You may have a look at this video too for reference: (Sharing Data between Components in Angular)

mymodel.ts (data to share)

// Some data we want to share against multiple components ...
export class mymodel {
    public data1: number;
    public data2: number;
    constructor(
    ) {
        this.data1 = 8;
        this.data2 = 45;
    }
}

Remember: There must be a parent that will share "mymodel" to child components.

Parent component

import { Component, OnInit } from '@angular/core';
import { mymodel } from './mymodel';
@Component({
    selector: 'app-view',
    template: '<!-- [model]="model" indicates you share model to the child component -->
        <app-mychild [model]="model" >
        </app-mychild>'

        <!-- I add another form component in my view,
         you will see two ways databinding is working :-) -->
        <app-mychild [model]="model" >
        </app-mychild>',
})

export class MainComponent implements OnInit {
    public model: mymodel;
    constructor() {
        this.model = new mymodel();
    }
    ngOnInit() {
    }
}

Child component, mychild.component.ts

import { Component, OnInit,Input } from '@angular/core';
import { FormsModule }   from '@angular/forms'; // <-- NgModel lives here
import { mymodel } from './mymodel';

@Component({
    selector: 'app-mychild',
    template: '
        <form #myForm="ngForm">
            <label>data1</label>
            <input type="number"  class="form-control" required id="data1 [(ngModel)]="model.data1" name="data1">
            <label>val {{model.data1}}</label>

            label>data2</label>
            <input  id="data2"  class="form-control" required [(ngModel)]="model.data2" name="data2" #data2="ngModel">
            <div [hidden]="data2.valid || data2.pristine"
                class="alert alert-danger">
                data2 is required
            </div>

            <label>val2 {{model.data2}}</label>
        </form>
    ',
})

export class MychildComponent implements OnInit {
    @Input() model: mymodel ;  // Here keywork @Input() is very important it indicates that model is an input for child component
    constructor() {
    }
    ngOnInit() {
    }
}

Note: In some rare cases, you may have error when the HTML code is parsed, because the model is not "ready" to use at the initialisation of the page. In this case, prefix the HTML code with an ngIf condition:

<div *ngIf="model"> {{model.data1}} </div>

It depends, if there is a simple case

a) A -> B -> C A has two child B and C and if you want to share data between A and B or A and C then use (input / output)

If you want to share between B and C then also you can use (input / output) but it is suggested to use Service.

b) If the tree is big and complex. (if there are so many levels of parent and children connections.) And in this case if you want to share data then I would suggest ngrx

It implements the flux architecture which creates a client side store to which any component can subscribe and can update without creating any race condition.

참고URL : https://stackoverflow.com/questions/31026886/how-do-i-share-data-between-components-in-angular-2

반응형