vxe-table鼠标移入行
近期的一个需求,就是左右分别都有一个表格,当鼠标移入左侧表格的某一行,对应右侧的数据行也会高亮显示。同理,右侧表格行移入之后,左侧对应表格的数据也会高亮显示。
我的想法
因为项目使用vxe-table框架,所有高版本是没有对应的api的,只能通过原生事件去触发。
import { isArray, isFunction, isString } from "lodash-es";
type Tr = HTMLTableRowElement;
type TrList = NodeListOf<Tr>;
type EventType = "mouseenter" | "mouseleave";
type TrEventCallBack = (ops: Omit<IItemTrFunCbParams, "callback">) => void;
interface ITrMouseEnterParams {
/** 表格tr选择器 */
selector: string;
/** 回调函数 */
callback?: TrEventCallBack;
}
interface IItemTrFunCbParams {
/** 鼠标事件对象或事件目标元素 */
row: MouseEvent | { target: Tr };
/** 行索引 */
rowIndex: number;
/** 事件类型 */
eventType: EventType;
/** 回调函数 */
callback?: TrEventCallBack;
}
interface IFindTableTrParams {
/** 表格tr选择器 */
selector: string;
/** 行索引数组 */
indexes: number[];
/** 事件类型 */
eventType: EventType;
}
// 使用WeakMap存储每个元素的事件处理函数引用
const eventHandlersMap = new WeakMap<
Tr,
{
mouseenter: (e: MouseEvent) => void;
mouseleave: (e: MouseEvent) => void;
}
>();
class HoverTableUtil {
static trColor = "#ff880019";
/**
* 查找表格tr元素并绑定鼠标移入移出事件
* @param param0 查找表格tr参数
* @returns 无返回值
*/
findTableTr({ selector, indexes, eventType }: IFindTableTrParams) {
if (!selector || !isString(selector)) return;
if (!isArray(indexes)) return;
for (let i = 0; i < indexes.length; i++) {
const item = indexes[i];
const tr = document.querySelectorAll(selector)[item] as Tr;
if (!tr) continue;
HoverTableUtil.itemTrFunCb({
row: { target: tr },
rowIndex: i,
eventType,
});
}
}
/**
* 表格tr鼠标移入事件回调函数
* @param param0 表格tr鼠标移入事件参数
* @returns 无返回值
*/
static itemTrFunCb({
row,
rowIndex,
eventType,
callback,
}: IItemTrFunCbParams) {
if (!row) return;
const target = row.target as Tr;
target.style.backgroundColor =
eventType === "mouseenter" ? HoverTableUtil.trColor : "";
if (isFunction(callback)) callback({ row, rowIndex, eventType });
}
/**
* 表格tr鼠标移入事件
* @param param0 表格tr鼠标移入事件参数
* @returns 无返回值
*/
trMouseEnter({ selector, callback }: ITrMouseEnterParams) {
if (!selector || !isString(selector)) return;
const trList: TrList = document.querySelectorAll(selector);
for (let i = 0; i < trList.length; i++) {
const item = trList[i];
const existingHandlers = eventHandlersMap.get(item);
if (existingHandlers) {
item.removeEventListener("mouseenter", existingHandlers.mouseenter);
item.removeEventListener("mouseleave", existingHandlers.mouseleave);
eventHandlersMap.delete(item);
}
// 创建新的事件处理函数
const mouseenterHandler = (row: MouseEvent) => {
HoverTableUtil.itemTrFunCb({
row,
rowIndex: i,
eventType: "mouseenter",
callback,
});
};
const mouseleaveHandler = (row: MouseEvent) => {
HoverTableUtil.itemTrFunCb({
row,
rowIndex: i,
eventType: "mouseleave",
callback,
});
};
// 保存函数引用
eventHandlersMap.set(item, {
mouseenter: mouseenterHandler,
mouseleave: mouseleaveHandler,
});
// 挂载事件
item.addEventListener("mouseenter", mouseenterHandler);
item.addEventListener("mouseleave", mouseleaveHandler);
}
}
}
export const hoverTableUtil = new HoverTableUtil();// 使用demo
watch(
() => data1.value,
val => {
hoverTableUtil.trMouseEnter({
selector: ".left-table table tbody tr",
callback: ({ rowIndex, eventType }) => {
hoverTableUtil.findTableTr({
selector: ".right-table table tbody tr",
indexes: [], // 高亮的索引合集
eventType,
});
},
});
}
);
watch(
() => data2.value,
val => {
hoverTableUtil.trMouseEnter({
selector: ".right-table table tbody tr",
callback: ({ rowIndex, eventType }) => {
hoverTableUtil.findTableTr({
selector: ".left-table table tbody tr",
indexes: [], // 高亮的索引合集
eventType,
});
},
});
}
);