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 确实解决了,表格排序后可以正常展开。但我们很快放弃了这个方案,主要基于以下两点考虑:
- 影响范围不明确 该组件被多处复用,删除 Child Row 的渲染逻辑可能会导致其他功能异常。
- 官方文档推荐 Material Table 官方文档明确建议使用两个 Row(Parent Row 和 Child Row)来实现分层渲染,我们希望尽量遵循最佳实践。
进一步排查
既然调整渲染方式并不符合实际需求,我们决定从渲染问题本身着手,通过浏览器开发工具(Elements 面板)检查实际渲染结果。
在对比分析中,我们发现一个关键问题:
排序后,原本应该渲染为 `Parent Row` 的内容,被错误地渲染为 `Child Row`,导致 `Parent Row` 无法展开。
从根本上看,渲染错误可能由以下几方面引起:
- 数据绑定问题
- 变更检测问题
- 数据顺序和结构问题
定位根因
经过逐一排查,最终发现问题源于 **数据顺序和结构问题**,而引发这一问题的核心是 `trackBy` 的实现。
在 `trackBy` 函数中,我们返回了 `row.id` 作为唯一标识符,但在排序的过程中,`row.id` 并不能反映数据的新位置,导致 Angular 的变更检测机制无法正确判断哪些 DOM 元素需要更新,从而引发渲染错误。
问题解决
通过修改 `trackBy` 函数,使其返回 `index` 和 `row.id` 的组合来唯一标识每一行,成功解决了这个问题:
trackByRow(index: number, row: any): any {return `${index}-${row.id}`; // 使用索引和ID的组合 }
总结
这个 Bug 的排查和解决过程让我们学到了一些重要的经验:
- trackBy 的作用 在 Angular 中,trackBy 用于优化 *ngFor 循环的性能,但使用时需要特别注意其唯一标识符的稳定性,尤其在排序、筛选等动态操作中,标识符必须能够反映数据的新状态。
- 分层排查的重要性 遇到问题时,从影响范围较小的模块(如排序函数)逐步向全局(如渲染逻辑和框架机制)排查,可以有效缩小问题范围。
- 遵循最佳实践 官方文档推荐的实现方式通常是经过深思熟虑的,应尽量在其基础上进行改进,而非彻底推翻。
通过这次问题的解决,我们不仅修复了 Bug,也加深了对 Angular 框架内部机制的理解。
相关文章:
Angular由一个bug说起之十一:排序之后无法展开 Row
问题现象 在使用 Material Table 时,排序功能触发了一个奇怪的 Bug:表格的 Row 无法展开。最终排查发现,问题的根源在于 trackBy 的错误使用。trackBy 方法接受两个参数:index(数据索引)和 row(…...
使用 Flutter 进行移动应用开发:深入探索
文章目录 前言一、介绍二、安装 Flutter 环境三、Flutter 应用结构与基础组件四、状态管理策略五、高级主题结语 前言 随着移动技术的迅猛发展,跨平台开发的需求日益增长。开发者们一直在寻找一种既能保证应用性能又能减少开发成本和时间的技术方案。Flutter 应运而…...
2024年天津市职业院校技能大赛高职组 “信息安全管理与评估”样题第三阶段
(四)第三阶段竞小组(赛项)目(300分) 第三阶段竞赛内容是:网络安全渗透(夺旗挑战赛CTF) 本模块要求参赛者作为攻击方,运用所学的信息收集、漏洞发现、漏洞利用等渗透测试技…...
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发布插件到私有仓库保姆级教程
在开发项目的过程中,我们经常需要安装插件依赖,那么怎么把自己开发的组件封装成一个插件,并发布到npm 插件市场或者上传到私有仓库里面呢?今天总结下自己发布插件到私有仓库的记录: 一、创建组件 执行命令创建一个空…...
WinRAR V7.10纯净体验
前言 很多同学在安装了WinRAR之后,每次用这个软件解压文件时,都会先跳出一个广。这个广就像打开了一个新窗口,很打扰人。从WinRAR的5.40版本开始,哪怕是简体中文版的,都会这样弹广告。不管你有没有注册账号࿰…...
scss文件内引入其他scss文件报错
1、今天在编译一些老项目的时候,老是提示下面信息 2、而且有很多Sass import rules are deprecated and will be removed in Dart Sass 3.0.0.警告 3、用npm view sass versions看,其中sass的最新版本是1.82.0 4、经过测试"sass": "1.75…...
1-12 GD32基于定时器输入捕获
前言: 基于本人对相关知识回顾与思考,仅供学习参考 目录 前言: 1.0 输入捕获 2.0 信号周期 3.0 定时器配置 4.0 定时器配置 5.0 定时器中断 后记: 1.0 输入捕获 2.0 信号周期 获取信号周期的方法,在第一次捕获与…...
前端基础的讲解-JS(22)
什么是JSON? 1.json 是一种轻量级的数据交换格式 简单来说:json 就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互。 类似于: 国际通用语言 - 英语 中国 56 个民族不同地区的通用语言 - 普通话 …...
Minecraft-Datapack数据包开发3-进度与成就
目录 简介成就与进度根进度叶子进度更多的检测方式 简介 代码已经上传: gitee github 成就与进度 工欲善其事必先利其器,别死记硬背,多使用自动生成网站 进度数据包生成器:https://misode.github.io/advancement/指令生成器&…...
泷羽sec-shell编程(3)
shell(3) 声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他…...
如何解决压测过程中JMeter堆内存溢出问题
如何解决压测过程中JMeter堆内存溢出问题 背景一、为什么会堆内存溢出?二、解决堆内存溢出措施三、堆内存参数应该怎么调整?四、堆内存大小配置建议 背景 Windows环境下使用JMeter压测运行一段时间后,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编写,因为是先开发了h5和app,小程序是突然要用的,做兼容开发已经来不及,由于微信小程序webview载入h5 因为通信必须要特殊限制(网页向小程序 postMessage 时,会在以下特定时机触发并收到消息&a…...
SSM01-MyBatis框架(一文学会MyBatis)
Mybatis框架 一、Mybatis框架简介 1.1 传统JDBC的缺陷 (1)数据库连接创建、释放频繁会造成系统资源浪费 【MyBatis通过在核心配置文件中配置数据路连接池解决此问题】 (2) SQL语句在代码中硬编码(PreparedStatement向占位符传…...
【PlantUML系列】状态图(六)
一、状态图的组成部分 状态:对象在其生命周期内可能处于的条件或情形,使用 state "State Name" as Statename 表示。初始状态:表示对象生命周期的开始,使用 [*] 表示。最终状态:表示对象生命周期的结束&…...
JS中重排和重绘的区别是什么?
在JavaScript中,当DOM(文档对象模型)发生变化时,浏览器需要重新计算和更新渲染树,这个过程通常涉及到重排(reflow)和重绘(repaint)。了解这两者之间的区别对于优化页面性…...
工业—使用Flink处理Kafka中的数据_ProduceRecord2
使用 Flink 消费 Kafka 中 ProduceRecord 主题的数据,统计在已经检验的产品中,各设备每 5 分钟 生产产品总数,将结果存入HBase 中的 gyflinkresult:Produce5minAgg 表, rowkey“...
C 库中的断言与 FreeRTOS 中的 trace 宏
在 C 编程领域,断言和 FreeRTOS 中的 trace 宏都有着独特而重要的作用。 一、断言(assert) 断言在一般的 C 库中是一个非常有用的工具,它以函数的形式存在。其核心作用在于对程序中的逻辑条件进行检查,确保特定的表达…...
JAVAWeb中的Servlet学习
一 Servlet简介 1.1动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源.例如:html css js img ,音频文件和视频文件 动态资源 需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成,例如Servle…...
英雄联盟智能助手Seraphine:免费开源的战绩查询与BP辅助神器
英雄联盟智能助手Seraphine:免费开源的战绩查询与BP辅助神器 【免费下载链接】Seraphine 英雄联盟战绩查询工具 项目地址: https://gitcode.com/gh_mirrors/se/Seraphine 还在为错过对局接受而懊恼吗?还在BP阶段犹豫不决错失最佳英雄选择吗&#…...
GalTransl代码架构分析:理解多进程插件系统的设计原理
GalTransl代码架构分析:理解多进程插件系统的设计原理 【免费下载链接】GalTransl 支持GPT-4/Claude/Deepseek/Sakura等大语言模型的Galgame自动化翻译解决方案 Automated translation solution for visual novels supporting GPT-4/Claude/Deepseek/Sakura 项目地…...
H3C HCL模拟器实战:IS-IS单区域基础配置与排错指南
1. 实验目标与网络环境准备如果你正在学习网络路由协议,特别是运营商级网络常用的IS-IS,那么通过模拟器进行实操是绕不开的一步。这次我用H3C的HCL模拟器,带大家走一遍IS-IS单区域的基本配置。这个实验的目标很明确:不是让你死记硬…...
三步搞定Windows磁盘空间不足:WinDirStat终极清理方案
三步搞定Windows磁盘空间不足:WinDirStat终极清理方案 【免费下载链接】windirstat WinDirStat is a disk usage statistics viewer and cleanup tool for Microsoft Windows 项目地址: https://gitcode.com/gh_mirrors/wi/windirstat 你是否经常遇到Windows…...
基于LangChain与Streamlit构建智能论文阅读助手:从原理到实践
1. 项目概述:一个为学术阅读而生的智能助手 如果你也经常被海量的学术论文淹没,或者对着PDF里复杂的公式和图表感到头疼,那么“talkingwallace/ChatGPT-Paper-Reader”这个项目,很可能就是你一直在寻找的“神兵利器”。这不仅仅是…...
3分钟快速解决iPhone USB网络共享问题:实用高效驱动安装指南
3分钟快速解决iPhone USB网络共享问题:实用高效驱动安装指南 【免费下载链接】Apple-Mobile-Drivers-Installer Powershell script to easily install Apple USB and Mobile Device Ethernet (USB Tethering) drivers on Windows! 项目地址: https://gitcode.com/…...
用Python搞定常微分方程:从显式RK4到隐式IRK6,一个类全搞定(附完整代码)
用Python搞定常微分方程:从显式RK4到隐式IRK6,一个类全搞定(附完整代码) 在工程计算和科学研究中,常微分方程(ODE)的数值求解是一个无法回避的问题。无论是模拟电路中的电流变化,还是…...
OpenClaw 落地企业微信:AI 驱动办公,效率提升看得见
前言 在企业数字化办公场景下,将智能对话功能与企业微信集成可有效提升内部沟通效率和业务响应速度。本文系统阐述了OpenClaw与企业微信的对接方案,该方案采用可视化操作界面实现智能机器人的快速部署,助力企业便捷构建专属AI助手࿰…...
153.YOLOv8 从数据集下载到 ONNX 部署
摘要 目标检测是计算机视觉领域的核心任务之一,YOLO系列算法凭借其单阶段检测架构和实时推理能力,成为工业界部署的首选方案。本文从零开始,系统讲解YOLOv8的完整使用流程,涵盖环境搭建、数据集构建、模型训练、评估与部署全链路。所有代码均基于Ultralytics官方库,提供可…...
OpenMetadata企业级元数据平台:智能化数据治理的架构革新与实践路径
OpenMetadata企业级元数据平台:智能化数据治理的架构革新与实践路径 【免费下载链接】OpenMetadata OpenMetadata is a unified metadata platform for data discovery, data observability, and data governance powered by a central metadata repository, in-dep…...
