在两个同级组件之间交换引用

Exchange references between two same-level components

我有两个 custom-component 由一个共同的父项生成,它们具有不同的数据作为 mat-tab-group 上的两个选项卡。

<mat-tab-group>
  <mat-tab label="TAB1">
    <ng-template matTabContent>
      <custom-component [data]="tab1data"></custom-component>
    </ng-template>
  </mat-tab>
  <mat-tab label="TAB2">
    <ng-template matTabContent>
      <custom-component [data]="tab2data"></custom-component>
    </ng-template>
  </mat-tab>
</mat-tab-group>

data 是一个 setter 设置内部 _data 并将其包装在 MatTableDataSource 中:

@Input()
set data(val: Data[]) {
    this._data = val;
    this.loadData();
}

loadData(): void {
    this.dataSource = new MatTableDataSource<Data>(this._data);
    this.dataSource.sort = this.sort;
}

我遇到的情况是第一个选项卡上的组件操作会影响另一个选项卡上的数据。 有没有什么方法可以传递组件引用,这样我就可以更改 _data 并从其他组件调用 loadData()

您可以使用 Rxjs observables 做到这一点

这是两个组件之间如何通信的 stackblitz 示例 https://stackblitz.com/edit/angular-ivy-myr2kh

my-service.service.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class MyServiceService {
  private dataChangeObservable = new Subject<any>();
    dataChangeStream = this.dataChangeObservable.asObservable();

  constructor() { }

  emitDataChange() {
    this.dataChangeObservable.next();
  }
}

ComponentOne.component.ts

onclickDiv() {
    this.myService.emitDataChange(); // Here you are triggering for change
}

ComponentTwo.component.ts

ngOnInit() {
    this.dataChangeSubscription$ = this.myService.dataChangeStream.subscribe(() => {
       this.count++; // Here you will get notified/listener of change
    })
 }

更新

如果你有相同的组件实例,那么你必须传递一些值来确定应该更新哪个实例

喜欢

https://stackblitz.com/edit/angular-ivy-4pznor

你的parenthtml

<app-componentone [name]="'one'"></app-componentone>
<app-componentone [name]="'two'"></app-componentone>

这里 onetwo 作为输入传递给只是为了识别实例

然后你的

import { Component, OnInit, Input } from '@angular/core';
import { MyServiceService } from '../my-service.service';

@Component({
   selector: 'app-componentone',
   templateUrl: './componentone.component.html',
   styleUrls: ['./componentone.component.css']
})
export class ComponentoneComponent implements OnInit {
  @Input() name; // it will have instance name
  count = 0;
  constructor(
     private myService: MyServiceService
  ) { }

  ngOnInit() {
    this.myService.dataChangeStream.subscribe((value) => { // here we will get to notify which instance should get updated
      if (this.name !== value) { // Here we checking for instance name for updating, if same component instance don't do anything else update
         this.count++;
      }
    })
  }

  onclickDiv() {
    // Here I am passing parameter, so if click is triggered from instance one, we have to update other instances, so passing parameter 'one' i.e. name, to avoid updating same component instance

    this.myService.emitDataChange(this.name);
  }
}

从您的第一个选项卡,您可以将 dataChange 的输出发送到其 parent 组件。

在自定义组件中有类似

的输出
@Output() public dataChange = new EventEmitter();

在数据更改时发出此事件,例如:-

this.dataChange.emit('changed data');

在该组件的选择器所在的 parent 组件中,将选择器更改为:-

HTML :-

<custom-component [data]="tab1data" (dataChange)="modifyDataTab2($event)"></custom-component>

TS :-

modifyDataTab2(firstTabData) {
   this.tab2Data = firstTabData;
   // or you can make other changes.
} 

现在,因为 tab2 已经将 tab2Data 作为输入,您的 loadData() 将自动被调用。

如果要在tab 2 change上修改tab1的数据,无需再次更改tab组件,每个实例都会有自己的输出。更改将仅在 parent 中进行。那将是:-

HTML :-

<custom-component [data]="tab2data" (dataChange)="modifyDataTab1($event)"></custom-component>

TS :-

modifyDataTab1(secondTabData) {
   this.tab1Data = secondTabData;
   // or you can make other changes.
} 

这就是拥有共同点的好处 parent。如果两个 child 想要交流,他们应该通过 parent 进行。因为作为输入传递的 parent 中的任何数据更改都会自动触发 child 中所需的更改。