Angular 由一个bug说起之二:trackBy的一点注意事项

trackBy是angualr优化项目性能的一种方法, 通过返回一个具有绑定性的唯一值, 比如id,手机号,身份证号之类的,来让angular能够跟踪数组的项目,根据数据的变化来重新生成DOM, 这样就节约了性能。

但是如果是使用ngFor循环组件,添加trackBy的时候就需要注意这个组件自身的数据更新机制是否正常,因为没有使用trackBy的时候,for循环的数组数据改变了,angular会把数组里所有的项目都重新生成,那些项目的组件也都会重新初始化。

但当你使用了trackBy,数据发生了变化,angular只会把那些数据有变化的项目重新生成,这样项目的组件也不会重新初始化,如果这个组件的数据更新机制不够好,这时就会因为数据更新的问题,产生bug。

接下来我用一个例子来演示一下

这是子组件test

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
})
export class TestComponent implements OnChanges {
    @Input() data: any;
    name: string;
    age: number;
    married: boolean;

    constructor() {

    }

    ngOnChanges(changes: SimpleChanges): void {
        if (changes.data?.currentValue) {
            this.init(changes.data?.currentValue);
        }
    }

    init(data) {
        this.name = data.name;
        this.age = data.age;
        this.married = this.married !== undefined ? this.married : data.married;
    }
}
<div>
    <div>姓名: {
    
    { name }} </div>
    <div>年龄: {
    
    { age }}</div>
    <div>婚否: {
    
    { married ? '已婚' : '未婚' }}</div>
</div>

这是父组件app

import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    itemArray = [
        {
            id: 1,
            data: {
                name: '张三',
                age: 24,
                married: true
            }
        },
        {
            id: 2,
            data: {
                name: '李四',
                age: 25,
                married: true
            }
        },
        {
            id: 1,
            data: {
                name: '王五',
                age: 26,
                married: false
            }
        },
    ];

    constructor() { }

    changeData() {
        this.itemArray = [
            {
                id: 1,
                data: {
                    name: '张三',
                    age: 24,
                    married: false
                }
            },
            {
                id: 2,
                data: {
                    name: '李四',
                    age: 25,
                    married: true
                }
            },
            {
                id: 1,
                data: {
                    name: '王五',
                    age: 26,
                    married: true
                }
            },
        ];
    }

}
<div>
    <div *ngFor="let item of itemArray;">
        <app-test [data]="item.data"></app-test>
        ------------------------------
    </div>
    <button (click)="changeData()">changeData</button>
</div>

我在这里循环一个数组,显示人物的资料,姓名,年龄,婚否。

接下来我改变一下数据,调用一下changeData,把张三变成未婚,王五变成已婚

数据正常更新了,这是没有加trackBy的时候,现在添加一下trackBy

trackByFn(index: number, item: any) {
        return item.id;
    }
<div>
    <div *ngFor="let item of itemArray; trackBy: trackByFn;">
        <app-test [data]="item.data"></app-test>
        ------------------------------
    </div>
    <button (click)="changeData()">changeData</button>
</div>

点击changeData

组件没有重新生成,数据也没有更新,这是因为test组件的更新机制有问题

他这里是以组件本身的数据为先,这样的话,即使上面传下来新数据,他也不会更新,除非重新初始化,而加个trackBy之后,组件就不会重新生成,所以没加trackBy之前,没有bug,加了就有bug。

所以,要使用trackBy,组件本身的数据更新机制要正常才行。

猜你喜欢

转载自blog.csdn.net/KenkoTech/article/details/134442862