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

Angular由一个bug说起之十一:排序之后无法展开 Row

问题现象

在使用 Material Table 时,排序功能触发了一个奇怪的 Bug:表格的 Row 无法展开。最终排查发现,问题的根源在于 `trackBy` 的错误使用。`trackBy` 方法接受两个参数:`index`(数据索引)和 `row`(当前行的数据)。在实现中,我们只使用了 `row` 参数,并返回了 `row.id` 作为唯一标识。但在排序的场景下,这种实现会导致渲染错误。

解决 Bug 的过程

初步排查

因为问题是在排序后出现的,我们最先检查了排序的函数实现。经过反复测试,发现排序逻辑是正确的,Bug 并不是由此引发。

接着,我们怀疑可能是 Material Table 的用法有误,于是对照官方文档检查了表格的用法配置,结果发现一切符合规范,没有发现明显的问题。

尝试解决

为了进一步缩小排查范围,我们尝试调整表格的渲染逻辑,将多个 Row 类型精简为单一类型。

调整前:

<!-- Parent Row -->
<tr mat-row *matRowDef="let row; columns: getColumns(context.columns);" (click)="toggleRow(row, $event)" [ngStyle]="row.style?.row" class="parent-refer"[attr.row-id]="row.id">
</tr><!-- Child Row -->
<tr mat-row *matRowDef="let row; columns: getColumns(context.columns); when: isChildRows;" [@detailExpand]="isRowExpanded(row) ? 'expanded' : 'collapsed'" [ngStyle]="row.style?.row" class="child-refer"[attr.row-id]="row.id">
</tr>

调整后:

<!-- Single Row -->
<tr mat-row *matRowDef="let row; columns: getColumns(context.columns);"  (click)="toggleRow(row, $event)" [ngStyle]="row.style?.row" class="parent-refer"[attr.row-id]="row.id">
</tr>

测试结果

Bug 确实解决了,表格排序后可以正常展开。但我们很快放弃了这个方案,主要基于以下两点考虑:

  1. 影响范围不明确 该组件被多处复用,删除 Child Row 的渲染逻辑可能会导致其他功能异常。
  2. 官方文档推荐 Material Table 官方文档明确建议使用两个 Row(Parent Row 和 Child Row)来实现分层渲染,我们希望尽量遵循最佳实践。

进一步排查

既然调整渲染方式并不符合实际需求,我们决定从渲染问题本身着手,通过浏览器开发工具(Elements 面板)检查实际渲染结果。

在对比分析中,我们发现一个关键问题:

排序后,原本应该渲染为 `Parent Row` 的内容,被错误地渲染为 `Child Row`,导致 `Parent Row` 无法展开。

从根本上看,渲染错误可能由以下几方面引起:

  1. 数据绑定问题
  2. 变更检测问题
  3. 数据顺序和结构问题

定位根因

经过逐一排查,最终发现问题源于 **数据顺序和结构问题**,而引发这一问题的核心是 `trackBy` 的实现。

 在 `trackBy` 函数中,我们返回了 `row.id` 作为唯一标识符,但在排序的过程中,`row.id` 并不能反映数据的新位置,导致 Angular 的变更检测机制无法正确判断哪些 DOM 元素需要更新,从而引发渲染错误。

问题解决

通过修改 `trackBy` 函数,使其返回 `index` 和 `row.id` 的组合来唯一标识每一行,成功解决了这个问题:

trackByRow(index: number, row: any): any {return `${index}-${row.id}`; // 使用索引和ID的组合
}

总结

这个 Bug 的排查和解决过程让我们学到了一些重要的经验:

  1. trackBy 的作用 在 Angular 中,trackBy 用于优化 *ngFor 循环的性能,但使用时需要特别注意其唯一标识符的稳定性,尤其在排序、筛选等动态操作中,标识符必须能够反映数据的新状态。
  2. 分层排查的重要性 遇到问题时,从影响范围较小的模块(如排序函数)逐步向全局(如渲染逻辑和框架机制)排查,可以有效缩小问题范围。
  3. 遵循最佳实践 官方文档推荐的实现方式通常是经过深思熟虑的,应尽量在其基础上进行改进,而非彻底推翻。

通过这次问题的解决,我们不仅修复了 Bug,也加深了对 Angular 框架内部机制的理解。

相关文章:

Angular由一个bug说起之十一:排序之后无法展开 Row

问题现象 在使用 Material Table 时&#xff0c;排序功能触发了一个奇怪的 Bug&#xff1a;表格的 Row 无法展开。最终排查发现&#xff0c;问题的根源在于 trackBy 的错误使用。trackBy 方法接受两个参数&#xff1a;index&#xff08;数据索引&#xff09;和 row&#xff08;…...

使用 Flutter 进行移动应用开发:深入探索

文章目录 前言一、介绍二、安装 Flutter 环境三、Flutter 应用结构与基础组件四、状态管理策略五、高级主题结语 前言 随着移动技术的迅猛发展&#xff0c;跨平台开发的需求日益增长。开发者们一直在寻找一种既能保证应用性能又能减少开发成本和时间的技术方案。Flutter 应运而…...

2024年天津市职业院校技能大赛高职组 “信息安全管理与评估”样题第三阶段

&#xff08;四&#xff09;第三阶段竞小组&#xff08;赛项&#xff09;目&#xff08;300分&#xff09; 第三阶段竞赛内容是:网络安全渗透&#xff08;夺旗挑战赛CTF&#xff09; 本模块要求参赛者作为攻击方&#xff0c;运用所学的信息收集、漏洞发现、漏洞利用等渗透测试技…...

docker批量创建cloudstack虚拟主机脚本

批量创建cloudstack脚本 #!/bin/bash # 配置变量 container_prefix"cloudworker-" base_ip"192.168.1." start_ip2 #开始ip start_container2 #上同 end_container4 #结束ip 包括 network_name"my_macvlan_network" image_name"dockedahi:…...

npm发布插件到私有仓库保姆级教程

在开发项目的过程中&#xff0c;我们经常需要安装插件依赖&#xff0c;那么怎么把自己开发的组件封装成一个插件&#xff0c;并发布到npm 插件市场或者上传到私有仓库里面呢&#xff1f;今天总结下自己发布插件到私有仓库的记录&#xff1a; 一、创建组件 执行命令创建一个空…...

WinRAR V7.10纯净体验

前言 很多同学在安装了WinRAR之后&#xff0c;每次用这个软件解压文件时&#xff0c;都会先跳出一个广。这个广就像打开了一个新窗口&#xff0c;很打扰人。从WinRAR的5.40版本开始&#xff0c;哪怕是简体中文版的&#xff0c;都会这样弹广告。不管你有没有注册账号&#xff0…...

scss文件内引入其他scss文件报错

1、今天在编译一些老项目的时候&#xff0c;老是提示下面信息 2、而且有很多Sass import rules are deprecated and will be removed in Dart Sass 3.0.0.警告 3、用npm view sass versions看&#xff0c;其中sass的最新版本是1.82.0 4、经过测试"sass": "1.75…...

1-12 GD32基于定时器输入捕获

前言&#xff1a; 基于本人对相关知识回顾与思考&#xff0c;仅供学习参考 目录 前言&#xff1a; 1.0 输入捕获 2.0 信号周期 3.0 定时器配置 4.0 定时器配置 5.0 定时器中断 后记&#xff1a; 1.0 输入捕获 2.0 信号周期 获取信号周期的方法&#xff0c;在第一次捕获与…...

前端基础的讲解-JS(22)

什么是JSON&#xff1f; 1.json 是一种轻量级的数据交换格式 简单来说&#xff1a;json 就是一种在各个编程语言中流通的数据格式&#xff0c;负责不同编程语言中的数据传递和交互。 类似于&#xff1a; 国际通用语言 - 英语 中国 56 个民族不同地区的通用语言 - 普通话 …...

Minecraft-Datapack数据包开发3-进度与成就

目录 简介成就与进度根进度叶子进度更多的检测方式 简介 代码已经上传&#xff1a; gitee github 成就与进度 工欲善其事必先利其器&#xff0c;别死记硬背&#xff0c;多使用自动生成网站 进度数据包生成器&#xff1a;https://misode.github.io/advancement/指令生成器&…...

泷羽sec-shell编程(3)

shell&#xff08;3&#xff09; 声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他…...

如何解决压测过程中JMeter堆内存溢出问题

如何解决压测过程中JMeter堆内存溢出问题 背景一、为什么会堆内存溢出&#xff1f;二、解决堆内存溢出措施三、堆内存参数应该怎么调整&#xff1f;四、堆内存大小配置建议 背景 Windows环境下使用JMeter压测运行一段时间后&#xff0c;JMeter日志窗口报错“java.lang.OutOfMe…...

爬虫项目基础知识详解

文章目录 Python爬虫项目基础知识一、爬虫与数据分析1.1 Python中的requests库Requests 库的安装Requests 库的 get() 方法爬取网页的通用代码框架HTTP 协议及 Requests 库方法Requests 库主要方法解析 1.2 python中的json库1.3 xpath学习之python中lxml库html了解html结构html…...

uniapp 微信小程序webview 和 h5数据通信

项目是uniapp编写&#xff0c;因为是先开发了h5和app&#xff0c;小程序是突然要用的&#xff0c;做兼容开发已经来不及&#xff0c;由于微信小程序webview载入h5 因为通信必须要特殊限制&#xff08;网页向小程序 postMessage 时&#xff0c;会在以下特定时机触发并收到消息&a…...

SSM01-MyBatis框架(一文学会MyBatis)

Mybatis框架 一、Mybatis框架简介 1.1 传统JDBC的缺陷 &#xff08;1&#xff09;数据库连接创建、释放频繁会造成系统资源浪费 【MyBatis通过在核心配置文件中配置数据路连接池解决此问题】 &#xff08;2&#xff09; SQL语句在代码中硬编码(PreparedStatement向占位符传…...

【PlantUML系列】状态图(六)

一、状态图的组成部分 状态&#xff1a;对象在其生命周期内可能处于的条件或情形&#xff0c;使用 state "State Name" as Statename 表示。初始状态&#xff1a;表示对象生命周期的开始&#xff0c;使用 [*] 表示。最终状态&#xff1a;表示对象生命周期的结束&…...

JS中重排和重绘的区别是什么?

在JavaScript中&#xff0c;当DOM&#xff08;文档对象模型&#xff09;发生变化时&#xff0c;浏览器需要重新计算和更新渲染树&#xff0c;这个过程通常涉及到重排&#xff08;reflow&#xff09;和重绘&#xff08;repaint&#xff09;。了解这两者之间的区别对于优化页面性…...

工业—使用Flink处理Kafka中的数据_ProduceRecord2

使用 Flink 消费 Kafka 中 ProduceRecord 主题的数据,统计在已经检验的产品中,各设备每 5 分钟 生产产品总数,将结果存入HBase 中的 gyflinkresult:Produce5minAgg 表, rowkey“...

C 库中的断言与 FreeRTOS 中的 trace 宏

在 C 编程领域&#xff0c;断言和 FreeRTOS 中的 trace 宏都有着独特而重要的作用。 一、断言&#xff08;assert&#xff09; 断言在一般的 C 库中是一个非常有用的工具&#xff0c;它以函数的形式存在。其核心作用在于对程序中的逻辑条件进行检查&#xff0c;确保特定的表达…...

JAVAWeb中的Servlet学习

一 Servlet简介 1.1动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源.例如:html css js img ,音频文件和视频文件 动态资源 需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成,例如Servle…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...