Angular 4 CLI中复用组件时HTML无法正确刷新的问题解决
解决Angular重复组件仅第一个刷新的问题
看起来你遇到的核心问题是多个相同子组件实例被错误复用了同一个引用,加上子组件没有响应输入数据的变化,导致第二个复选框触发时只有第一个表格更新。下面是一步步的解决方案:
问题根源分析
- 你用
@ViewChild(SampleComponent)只能获取到DOM中第一个SampleComponent实例,所以不管调用showSample1()还是showSample2(),实际操作的都是第一个表格组件。 - 子组件的
loadgriddata()只在ngOnInit()中执行一次,而ngOnInit仅在组件初始化时运行,当父组件更新sample1/sample2时,子组件不会自动重新加载数据。 - 手动调用子组件的
ngOnInit()是不符合Angular生命周期规范的做法,容易引发不可预期的问题。
修正方案
步骤1:给子组件添加模板引用变量
在父组件的HTML中,给每个sample-table添加唯一的模板引用,这样可以精准获取每个子组件实例:
<div fxLayout="row"> <mat-checkbox color="warn" [(ngModel)]="showDeleted1" (change)="showSample1()"> <span class="helper-legend legend-red"></span> Show Deleted </mat-checkbox> <sample-table #table1 [sample]="sample1"></sample-table> </div> <div fxLayout="row"> <mat-checkbox color="warn" [(ngModel)]="showDeleted2" (change)="showSample2()"> <span class="helper-legend legend-red"></span> Show Deleted </mat-checkbox> <sample-table #table2 [sample]="sample2"></sample-table> </div>
步骤2:父组件获取各自的子组件实例
修改父组件的TS代码,通过模板引用变量分别获取两个子组件,并在对应的方法中操作各自的实例:
import { Component, OnInit, ViewChild } from '@angular/core'; import { Sample } from '../../models/sample'; import { SampleComponent } from './sample.component'; // 确保导入路径正确 @Component({ selector: 'demo', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { sample1: Sample = new Sample(); sample2: Sample = new Sample(); showDeleted1 = false; showDeleted2 = false; // 通过模板引用获取每个子组件实例 @ViewChild('table1') table1!: SampleComponent; @ViewChild('table2') table2!: SampleComponent; constructor() { } ngOnInit() { // 初始化加载两个表格的数据 this.table1.loadgriddata(); this.table2.loadgriddata(); } showSample1() { this.sample1.deleteFlag = this.showDeleted1 ? 1 : 0; // 调用第一个表格的加载方法 this.table1.loadgriddata(); } showSample2() { this.sample2.deleteFlag = this.showDeleted2 ? 1 : 0; // 调用第二个表格的加载方法 this.table2.loadgriddata(); } }
步骤3:子组件响应输入数据变化
修改子组件的TS代码,实现OnChanges接口,当父组件传递的sample参数变化时,自动重新加载数据:
import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core'; import { Sample } from '../../models/sample'; import { YourSampleService } from '../../services/your-sample.service'; // 替换成你的实际服务 @Component({ selector: 'sample-table', templateUrl: './sample.component.html' }) export class SampleComponent implements OnInit, OnChanges { @Input() sample!: Sample; samples: Sample[] = []; // 注意:p-table的[value]需要绑定数组,这里修正变量名 constructor(private service: YourSampleService) { } ngOnInit() { this.loadgriddata(); } // 监听输入参数变化,自动刷新数据 ngOnChanges(changes: SimpleChanges) { // 排除初始化时的第一次变化,避免重复加载 if (changes['sample'] && !changes['sample'].firstChange) { this.loadgriddata(); } } loadgriddata() { this.service.getData(this.sample).subscribe( res => { this.samples = res; // 将返回的数组赋值给samples,对应p-table的[value] }, () => alert("加载数据失败") ); } }
额外修正:子组件HTML变量绑定
确保子组件的p-table绑定的是正确的数组变量:
<div> <p-table [value]="samples" #dt customSort="true"> <ng-template pTemplate="header"> <tr> <th> Date </th> <th> Type </th> </tr> </ng-template> <ng-template pTemplate="body" let-sample let-rowIndex="rowIndex"> <tr> <td>{{sample.date | date:'MM/dd/yy HH:mm'}}</td> <td>{{sample.type | slice: 0:50}}</td> </tr> </ng-template> </p-table> </div>
关键要点总结
- 精准获取子组件实例:用模板引用变量+
@ViewChild可以单独控制每个子组件,避免多个实例共用同一个引用的问题。 - 响应输入变化:通过
ngOnChanges让子组件自动感知输入数据的变化,无需手动调用生命周期钩子。 - 遵循Angular规范:不要手动调用
ngOnInit()等生命周期方法,让框架的变更检测机制处理组件更新。
内容的提问来源于stack exchange,提问作者Venkateswaran R
相关产品推荐
相关产品推荐

