javascript - 为什么在修改类的本地属性时会执行 ngOnChanges?
问题描述
我已经处理这种情况一段时间了,我提前感谢您的建议
ngOnChanges
在我理解它不应该运行的上下文中运行。当修改最初通过@Input
. 这种修改会导致ngOnchanges
钩子在一个上下文中执行,而不是在另一个上下文中执行。我在下面描述我的场景
我有以下父组件,其中包含传递给子组件的客户列表,
父控制器
export class AppComponent {
customers: ICustomer[];
currentlySelected: Option = 'All';
constructor() {
this.customers = [
{
id: 1,
name: 'Task1',
status: 'Pending',
},
{
id: 2,
name: 'Task2',
status: 'Pending',
},
{
id: 3,
name: 'Task3',
status: 'Progress',
},
{
id: 4,
name: 'Task4',
status: 'Closed',
},
];
}
selectBy(option: Option): void {
this.currentlySelected = option;
}
filterBy(): ICustomer[] {
if (this.currentlySelected === 'All') {
return this.customers;
}
return this.customers.filter(
(customer) => customer.status === this.currentlySelected
);
}
}
父模板
<nav>
<ul>
<li (click)="selectBy('All')">All</li>
<li (click)="selectBy('Pending')">Pending</li>
<li (click)="selectBy('Progress')">Progress</li>
<li (click)="selectBy('Closed')">Closed</li>
</ul>
</nav>
<app-list [customers]="filterBy()"></app-list>
在将客户传递给子组件之前,它们会根据客户状态属性进行过滤,这就是该filterBy
函数的目的。
钩子中的子组件ngOnChanges
通过添加属性来修改每个客户showDetail
并为其分配值false
export class ListComponent implements OnInit, OnChanges {
@Input() customers: ICustomer[] = [];
constructor() {}
ngOnChanges(changes: SimpleChanges): void {
this.customers = changes.customers.currentValue.map(
(customer: ICustomer) => ({
...customer,
showDetail: false,
})
);
}
ngOnInit(): void {
console.log('init');
}
toggleDetail(current: ICustomer): void {
this.customers = this.customers.map((customer: ICustomer) =>
customer.id === current.id
? { ...customer, showDetail: !customer.showDetail }
: { ...customer }
);
}
}
调用该toggleDetail
方法会更改showDetail
属性的值以显示客户的详细信息
子模板
<table>
<thead>
<tr>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let customer of customers">
<tr>
<td>{{ customer.name }}</td>
<td>
<button (click)="toggleDetail(customer)">Detail</button>
</td>
</tr>
<tr *ngIf="customer.showDetail">
<td colspan="2">
<pre>
{{ customer | json }}
</pre>
</td>
</tr>
</ng-container>
</tbody>
</table>
发生的行为如下,当列出所有客户端并单击详细信息时,它按预期工作,但是如果我更改为另一个状态并且列表已更新并且我单击详细信息,它不会显示详细信息。原因是ngOnchanges
钩子被重新执行导致showDetail
属性再次设置为 false,从而违背了我的意图。
为什么ngOnChanges
在这种情况下执行?有什么办法可以解决?
更新 1
我添加了示例应用程序:https ://stackblitz.com/edit/angular-ivy-dkvvgt?file=src/list/list.component.html
解决方案
你的代码中有
<app-list [customers]="filterBy()"></app-list>
Angular 在执行之前无法知道函数“filterBy”的结果,因此每次检查时都会执行它。这就是我们应该避免在 .html 中使用函数的原因(当然,我们可以使用,但我们需要考虑到这是有代价的)。使用辅助变量
customerFilter:ICustomer[];
在构造函数中添加
constructor() {
this.customers = [...]
this.customerFilter=this.customers //<--add this line
}
并在 selectBy
selectBy(option: Option): void {
this.currentlySelected = option;
this.customerFilter=this.filterBy() //<--this line
}
现在将 customerFilter 作为参数传递
<app-list [customers]="customerFilter"></app-list>
你的分叉堆栈闪电战
推荐阅读
- salesforce - Lightning Web 组件专家超级徽章:挑战 7
- mysql - 运行springboot项目时出现SQLSyntaxErrorException
- javascript - 设置卡片样式会导致 TextField 在 Material UI + React 中失去焦点
- html - 为什么@font-face 在我的样式表中失败?
- javascript - 用 html 视频对漂亮的 dnd 做出反应,而不是冒泡事件
- reactjs - Azure 应用服务静态网站 routes.json 不起作用
- flutter - 如何捕获 ERROR_REQUIRES_RECENT_LOGIN?
- ruby-on-rails - Rails 6 APi 从用户出生日期过滤用户年龄
- python - 子进程没有捕获标准输出
- python - Python Mixins:*args/**kwargs 与显式调用`__init__`