如何让ngOnChanges仅在mat-tab-group的活跃标签页中触发?
问题描述
父组件向子组件传递data数据时,两个子组件实例的ngOnChanges方法都会被调用,引发数据共享问题。尝试用mat-tab的isActive属性限制仅活跃标签页执行相关方法,但未生效。需要实现ngOnChanges仅在活跃标签页触发,或彻底解决数据共享问题。
父组件代码 (parent.component.ts)
export class ParentComponent implements OnInit { tabs=['tab1','tab2'] data={} constructor() { } ngOnInit(): void { this.data={} } tabChange(event:any){ console.log(event) let index=event.index this.data={} } hitinit(){ this.data={id:"1",name:"sample"} } }
父组件模板 (parent.component.html)
<div> <mat-tab-group (selectedTabChange)="tabChange($event)"> <mat-tab *ngFor="let tab of tabs;let i=index" #tabname> <ng-template mat-tab-label> <span>{{tab}}</span> </ng-template> <app-child [isActive]="tabname.isActive" [data]="data"></app-child> </mat-tab> </mat-tab-group> <button (click)="hitinit()">Hit</button> </div>
子组件代码 (child.component.ts)
export class ChildComponent { form=new FormGroup({ name:new FormControl('') }); id:any @Input() public data:any @Input() public isActive!:boolean constructor() { } ngOnInit(){ this.id=this.data.id } ngOnChanges(): void { console.log(this.isActive) this.method() } method(){ if(this.isActive) this.form.patchValue(this.data) } }
子组件模板 (child.component.html)
<form [formGroup]="form"> <input matInput formControlName="name"/> </form>
解决方案
方法一:精准控制ngOnChanges执行逻辑
问题核心是ngOnChanges触发时,isActive的更新可能滞后于data的变化。可以通过SimpleChanges参数判断变化属性,结合当前标签活跃状态过滤:
修改子组件的ngOnChanges(需先导入SimpleChanges):
import { SimpleChanges } from '@angular/core'; // ... ngOnChanges(changes: SimpleChanges): void { // 仅当data发生变化且当前标签活跃时执行更新 if (changes['data'] && this.isActive) { this.form.patchValue(this.data); } }
方法二:为每个标签维护独立数据
彻底解决数据共享问题,给每个标签页分配独立的data对象,避免所有子组件共用同一数据源:
修改父组件:
export class ParentComponent implements OnInit { tabs = ['tab1', 'tab2']; // 为每个标签创建独立数据容器 tabData: { [key: string]: any } = { tab1: {}, tab2: {} }; activeTab = 'tab1'; constructor() { } ngOnInit(): void { } tabChange(event: any) { this.activeTab = this.tabs[event.index]; } hitinit() { // 仅更新当前活跃标签的数据 this.tabData[this.activeTab] = { id: "1", name: "sample" }; } }
修改父组件模板:
<div> <mat-tab-group (selectedTabChange)="tabChange($event)"> <mat-tab *ngFor="let tab of tabs;let i=index"> <ng-template mat-tab-label> <span>{{tab}}</span> </ng-template> <app-child [data]="tabData[tab]"></app-child> </mat-tab> </mat-tab-group> <button (click)="hitinit()">Hit</button> </div>
这种方式下,每个子组件绑定独立数据对象,ngOnChanges只会在对应标签的数据更新时触发,从根源避免共享问题。
方法三:启用mat-tab懒加载
mat-tab默认预加载所有标签内容,开启懒加载后,仅当标签激活时才创建子组件实例,未激活标签不会触发ngOnChanges:
修改父组件模板,用ng-template matTabContent包裹子组件:
<div> <mat-tab-group (selectedTabChange)="tabChange($event)"> <mat-tab *ngFor="let tab of tabs;let i=index"> <ng-template mat-tab-label> <span>{{tab}}</span> </ng-template> <ng-template matTabContent> <app-child [data]="data"></app-child> </ng-template> </mat-tab> </mat-tab-group> <button (click)="hitinit()">Hit</button> </div>
注意:懒加载模式下切换标签会重新创建组件实例,适合轻量组件场景。
内容的提问来源于stack exchange,提问作者elisa relhan
相关产品推荐
相关产品推荐

