Angular onPush检测机制相关问题
问题的产生: 搜索学习 Angular onPush
相关知识,还原一篇文章中的例子,结果没有出现文章中提到的问题.
onPush检测机制的执行条件是只有当传入的值有变化.简单类型是值变化,而复杂类型是引用变化,才会执行组件内部的state更新然后更新视图。经常使用 xxx.slice()
,这个 xxx
应该是一种什么数据结构 ?
文章中代码如下:
add (): void {
this.employeeList.unshift(new Employee('haha', 15))
this.employeeList = this.employeeList.slice()
}
我还原的this.employeeList
结构如下:
employeeList: Employee[] = [
{
name: "软件开发工程师",
rate: 4,
},
{
name: "业务设计师",
rate: 5,
},
]
也就是说,我还原的代码,没有使用 this.employeeList.slice()
这句,数据就变化了.
原文章: https://zhuanlan.zhihu.com/p/...
恢复文章的例子:
1.Employee.ts
export class Employee {
name: string;
rate: number;
constructor(name, rate) {
this.name = name;
this.rate = rate;
}
}
2.app.component.ts
export class AppComponent {
title = 'hello-angular';
departmentName = 'Front End'
employeeList: Employee[] = [
{
name: "PPQA",
rate: 3,
},
{
name: "软件开发工程师",
rate: 4,
},
{
name: "业务设计师",
rate: 5,
},
{
name: "UI设计师",
rate: 6,
},
{
name: "销售代表",
rate: 7,
},
]
add (): void {
console.log(123)
this.employeeList.push(new Employee('中国航天科工工程总院客户联络代表', Math.floor((Math.random()*10)+30)))
this.employeeList = this.employeeList.slice() // 此行删除,数据也会更新
}
addEnter (name: string): void {
console.log(456)
this.employeeList.unshift(new Employee(name, Math.floor((Math.random()*10)+30)))
this.employeeList = this.employeeList.slice()
}
removeThis (employee: Employee): void {
console.log(employee)
this.employeeList = this.employeeList.filter((item) => {
return !employee.name.includes(item.name)
});
}
}
3.app.component.html
<button (click)="add()">add</button>
<app-employee-list [departmentName]='departmentName' [employeeList]="employeeList" (add)="addEnter($event)" (remove)="removeThis($event)"></app-employee-list>
4.employee-list.component.ts
import { Component, Input, Output, EventEmitter } from "@angular/core";
import { Employee } from './Employee';
const fibonacci = (num: number): number => {
if (num === 1 || num === 2) {
return 1;
}
return fibonacci(num - 1) + fibonacci(num - 2);
}
@Component({
selector: 'employee-list',
templateUrl: './Employee.component.html',
styleUrls: ['./Employee.component.scss']
})
export class EmployeeListComponent {
@Input() departmentName: string
@Input() employeeList: Employee[]
@Output() remove = new EventEmitter<Employee>()
@Output() add = new EventEmitter<string>()
name: string
handleKey (event: any): void {
if (event.keyCode === 13) {
this.add.emit(this.name)
this.name = ''
}
}
handleRemove (employee: Employee): void {
this.remove.emit(employee)
}
calculate (num: number) {
return fibonacci(num)
}
}
5.employee-list.component.html
<div class="employee-container">
<h1>{{ departmentName }}</h1>
<p>
<label for="employee"></label>
<input type="text" id="employee" placeholder="please input a employee name" [(ngModel)]="name" (keydown)="handleKey($event)" />
</p>
<ul>
<li *ngFor="let employee of employeeList">
<span>{{ employee.name }}</span>
<span class="rate">{{ calculate(employee.rate) }}</span>
<button (click)="handleRemove(employee)">delete</button>
</li>
</ul>
</div>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
xxx是个数组。
slice()是数组的一个方法.
xxx = xxx.slice();
作用是:复制xxx数组,并使用复制后的值来替换xxx。此时
xxx
由原数组变更为与原数组完全相同的新数组。但由于是新数组的原因,所以xxx的引用值变更了,此时则会触发检测条件。从而使得重新对视图进行渲染。看你发了不少关于angular的文章,个人建议还是多实践,只有自己动手的时候碰到问题了,解决问题的方法才会过目不忘。你现在看似学的快,但实际上大脑可能已经忘却了很多以前学过的东西。
感觉没有必要非得找个不更新的例子试。angular的检测机制,在大多数情况下都是可以感知到更新的(哪怕你是数组)。
可以试试如下代码:
前段时间遇到过同样的问题,按文档上
OnPush
策略下, 数组push 数据,页面不应该变化,理论上只有引用改变才会触发试图更新,后来发现 跟ngfor指令和trackByFn有关,如果是一个对象,在onPush 模式下,对象的属性发生变化,视图不会更新。