当前位置: 首页 > news >正文

Angular-使用好NgForOf的trackBy带来性能上的提升

首发于: zhuanlan.zhihu.com/c_106067616…

官方文档,查看“变更的传导机制”即有详细的表述:

即使数据没有变化,迭代器中的元素标识符也可能会发生变化。比如,如果迭代器处理的目标是通过 RPC 从服务器取来的, 而 RPC 又重新执行了一次。那么即使数据没有变化,第二次的响应体还是会生成一些具有不同标识符的对象。Angular 将会清除整个 DOM, 并重建它(就仿佛把所有老的元素都删除,并插入所有新元素)。这是很昂贵的操作,应该尽力避免。
NgForOf - Angular 官方文档
那么如何来避免呢?
要想自定义默认的跟踪算法, NgForOf支持trackBy选项。trackBy接受一个带两个参数(index和 item)的函数。 如果给出了trackBy,Angular 就会使用该函数的返回值来跟踪变化。
可惜官网提供的例子无法运行,自己来个例子似乎会更好理解:
  1. 假设有这样的一个html
<a (click)="add()">添加</a>
<ul>
  <li 
    *ngFor="let i of arr; index as ii; trackBy: trackFunc">
    {{i.id}} / {{ i.name }}
   </li>
</ul>复制代码
2. 然后来点ts
arr = [
  { id: 1, name: 'a' },
  { id: 2, name: 'b' },
  { id: 3, name: 'c' },
  { id: 4, name: 'e' }
];

trackFunc = (index, item) => {
  // 改变这里查看页面dom刷新状况
  return index;
  // return 'xxx';
  // return item.id;
  // return item.name;
 };

 add() {
   const last = this.arr[this.arr.length - 1];
   this.arr.unshift({
     id: last.id, // 新加的元素id与开始定义的最后一个元素id相同,请注意!
     name: Math.random().toString() // 新加的元素name是随机字符
   });
 }复制代码
3. 运行
以不停的往数组开始插入元素,查看页面刷新的情况。
(1)return index;
刷新全部li
(2)return item.id;
只会刷新id相同的li
(3)return item.name;
只会刷新name变化的li
(4)return 'xxx'; 纯粹搞事情。。。
情况跟return index一样,刷新全部的li

通过以上的实践可知:

(1)return index: 数组索引变化触发刷新。
(2)return item.id: 最后个元素Id与新增的元素id相同,但也在刷新;但id为1,2,3的元素,从未刷新;似乎这里只能从源码中一探究竟。
(3)return item.name: name属性变化触发了刷新。
(4)return 'xxx': 返回与index和item都不相关的固定值,也会触发全部刷新。
抛开第二点得出一个猜测结果:使用trackBy的好处是自定义返回跟踪结果,以比对上次的跟踪结果,如果不一样,那么就刷新变化的页面实例(减少不必要的dom刷新而带来性能的提升)。


附上一个关于ngFor如何实现的回答: stackoverflow.com/questions/4…
最终附上在线代码: stackblitz.com/edit/angula…

转载于:https://juejin.im/post/5cc56dd26fb9a0322861726f

相关文章:

  • 微服务
  • 一篇文章告诉你Python上下文管理器怎么用
  • python算法之插入排序
  • swift学习笔记1
  • 关于可变参数varargs
  • Educational Codeforces Round 64 -C(二分)
  • Windows 10一个很愚蠢的做法
  • 英语影视台词---无敌破坏王2大脑互联网
  • 开源CMS比较
  • 《Linux就该这么学》第2章 新手必须掌握的Linux命令
  • 火狐浏览器问题踩坑
  • Qtum量子链周报(4月29日-5月5日)
  • vue配合webpack使用sentry对错误日志监控
  • Leetcode PHP题解--D54 937. Reorder Log Files
  • upc组队赛18 THE WORLD【时间模拟】
  • bootstrap创建登录注册页面
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • JAVA 学习IO流
  • Java编程基础24——递归练习
  • Kibana配置logstash,报表一体化
  • Markdown 语法简单说明
  • opencv python Meanshift 和 Camshift
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 从零开始的无人驾驶 1
  • 代理模式
  • 对超线程几个不同角度的解释
  • 前嗅ForeSpider教程:创建模板
  • 通过git安装npm私有模块
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 携程小程序初体验
  • 责任链模式的两种实现
  • Linux权限管理(week1_day5)--技术流ken
  • #Linux(make工具和makefile文件以及makefile语法)
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (2015)JS ES6 必知的十个 特性
  • (39)STM32——FLASH闪存
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (BFS)hdoj2377-Bus Pass
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (poj1.3.2)1791(构造法模拟)
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (规划)24届春招和25届暑假实习路线准备规划
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (转)使用VMware vSphere标准交换机设置网络连接
  • (转)详解PHP处理密码的几种方式
  • (转载)虚函数剖析
  • .apk 成为历史!
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .dwp和.webpart的区别
  • .NET 8.0 中有哪些新的变化?
  • .NET 使用 XPath 来读写 XML 文件
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)