故事发生在2025/4/7,简单阐述一下故事背景吧,我们需要实现一个hover隔行的效果。当我们hover在任意一行的时候,与当前hover的这一行每相隔n行也需要有高亮的样式。

技术栈
在本次需求开发中,是react、antd pro、scss这三个核心技术
之前的写法
用到了两个状态 第一个状态:hoverSpace
(决定隔多少行显示下个高亮),第二个状态:hoverRowIndex
(当前鼠标所处的行的索引)
先介绍一下公司前面的人实现这个需求的思路吧,首先给每表格的每一行绑定两个事件,分别是onMouseEnter、onMouseLeave这两个,当鼠标移入表格行的时候,将当前行所处的索引记录下来,当移出当前行的时候将当前行所引设置为null,然后根据这两个变量计算出哪些行需要高亮,然后动态设置高亮类名。
代码展示
因为项目源代码较长,所以这里就只展示关键代码了,主要看思路
tsx
// table.tsx
import { ProTable } from "@ant-design/pro-components";
const Table = () => {
const [hoverSpace, setHoverSpace] = useState(0);
const [hoverRowIndex, setHoverRowIndex] = useState<number | null>(null);
return (
<ProTable
rowClassName={(_, index) => {
if (hoverSpace && hoverRowIndex !== null) {
return (index - hoverRowIndex) % (hoverSpace + 1) === 0
? "ant-table-cell-row-hover"
: "";
}
}}
onRow={(_, index) => ({
onMouseEnter: () => {
setHoverRowIndex(index);
},
onMouseLeave: () => {
setHoverRowIndex(null);
},
})}
/>
);
};
export default Table;
卡顿原因分析
因为这个组件所挂载的dom比较多,所以这个页面渲染所需要的时间就比较长,而在react中当组件的props,或者组件中的状态更新了,那么这个组件就会重新渲染一次,当然,还有很多其他的原因也会导致组件重新渲染,这里就不一一列举了。而在这个案例中,当我们的鼠标不断在表格行中上下移动,导致hoverRowIndex这个状态频繁更新,进而导致组件频繁渲染。最终导致页面卡顿。
解决方案选择
根据上面已经分析出了原因,那么就针对这个问题进行优化解决。第一个方案:让组件渲染不要那么频繁,或者让组件的部分渲染,而不是整个重新渲染。第二个方案:不用第二个状态,用纯css完成,这个组件就不用重新渲染了。一开始就想用第一种方案,但是想了很久没想到一个比较好的解决方式,于是决定用第二种方式。
解决方式思路
在最开始的时候想到的是用:nth-child()
这个伪类去实现,但是好像没不能满足hover时才出现的效果,后面想要兄弟选择器去选择(但是这个选择器只能选中当前这个元素后面的元素)
实现代码
ts
//table.tsx
import { ProTable } from "@ant-design/pro-components";
import styles from "./index.module.scss";
const Table = () => {
const [hoverSpace, setHoverSpace] = useState(0);
return (
<ProTable
className={styles["table-container"]}
rowClassName={(_, index) => {
if (hoverSpace === 0) {
return "";
}
return styles[`row-id-row-${index % (Number(hoverSpace) + 1)}`];
}}
/>
);
};
export default Table;
scss
// index.module.scss
.table-container {
@for $i from 0 through 11 {
.row-id-row-#{$i}:hover,
.row-id-row-#{$i}:hover ~ .row-id-row-#{$i} {
td {
background-color: #afdbfd !important;
}
}
}
}
到这里本篇文章就结束啦,如果本文有哪些错误,还请各位大佬指正,有什么更好的实现方法也欢迎大佬们分享出来,供我这个小菜鸡学习学习,非常感谢......