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


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

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

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

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

    这是子组件test

    1. import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
    2. @Component({
    3. selector: 'app-test',
    4. templateUrl: './test.component.html',
    5. styleUrls: ['./test.component.css']
    6. })
    7. export class TestComponent implements OnChanges {
    8. @Input() data: any;
    9. name: string;
    10. age: number;
    11. married: boolean;
    12. constructor() {
    13. }
    14. ngOnChanges(changes: SimpleChanges): void {
    15. if (changes.data?.currentValue) {
    16. this.init(changes.data?.currentValue);
    17. }
    18. }
    19. init(data) {
    20. this.name = data.name;
    21. this.age = data.age;
    22. this.married = this.married !== undefined ? this.married : data.married;
    23. }
    24. }
    1. <div>
    2. <div>姓名: {{ name }} div>
    3. <div>年龄: {{ age }}div>
    4. <div>婚否: {{ married ? '已婚' : '未婚' }}div>
    5. div>

    这是父组件app

    1. import { Component } from '@angular/core';
    2. @Component({
    3. selector: 'app-root',
    4. templateUrl: './app.component.html',
    5. styleUrls: ['./app.component.css']
    6. })
    7. export class AppComponent {
    8. itemArray = [
    9. {
    10. id: 1,
    11. data: {
    12. name: '张三',
    13. age: 24,
    14. married: true
    15. }
    16. },
    17. {
    18. id: 2,
    19. data: {
    20. name: '李四',
    21. age: 25,
    22. married: true
    23. }
    24. },
    25. {
    26. id: 1,
    27. data: {
    28. name: '王五',
    29. age: 26,
    30. married: false
    31. }
    32. },
    33. ];
    34. constructor() { }
    35. changeData() {
    36. this.itemArray = [
    37. {
    38. id: 1,
    39. data: {
    40. name: '张三',
    41. age: 24,
    42. married: false
    43. }
    44. },
    45. {
    46. id: 2,
    47. data: {
    48. name: '李四',
    49. age: 25,
    50. married: true
    51. }
    52. },
    53. {
    54. id: 1,
    55. data: {
    56. name: '王五',
    57. age: 26,
    58. married: true
    59. }
    60. },
    61. ];
    62. }
    63. }
    1. <div>
    2. <div *ngFor="let item of itemArray;">
    3. <app-test [data]="item.data">app-test>
    4. ------------------------------
    5. div>
    6. <button (click)="changeData()">changeDatabutton>
    7. div>

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

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

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

    1. trackByFn(index: number, item: any) {
    2. return item.id;
    3. }
    1. <div>
    2. <div *ngFor="let item of itemArray; trackBy: trackByFn;">
    3. <app-test [data]="item.data">app-test>
    4. ------------------------------
    5. div>
    6. <button (click)="changeData()">changeDatabutton>
    7. div>

    点击changeData

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

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

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

  • 相关阅读:
    Html 引入element UI + vue3 报错Failed to resolve component: el-button
    视频剪辑技巧:如何高效地将多个视频合并成一个新视频
    vue2.x 迭代更新项目去掉缓存处理
    Web前端-Vue2+Vue3基础入门到实战项目-Day3(生命周期, 案例-小黑记账清单, 工程化开发入门)
    浅谈常态化压测 | 京东物流技术团队
    Android - Service
    剑指 Offer 56 数组中数字出现的次数(异或)
    分类预测 | MATLAB实现ELM极限学习机多特征分类预测(二分类)
    你们还不知道这几个实用的思维导图app吗?
    【飞控调试】DJIF450机架+Pixhawk6c mini+v1.13.3固件+好盈Platinium 40A电调无人机调试
  • 原文地址:https://blog.csdn.net/KenkoTech/article/details/134442862