Element UI Table组件扩展:实现鼠标横向滚动和提示功能(欢迎指导)
前言
在使用Element UI的Table组件时,当表格列数较多时,需要通过水平滚动条来查看更多的列数据。为了提升用户体验,我们可以通过扩展Table组件,实现使用鼠标滚轮进行横向滚动的功能,并添加相应的提示信息。本文将详细介绍如何实现这一功能。
功能特点
- 支持使用鼠标滚轮进行横向滚动(按住Alt键)
- 自动检测表格是否需要横向滚动
- 提供可配置的提示信息和位置
- 支持双击切换滚动方向(垂直/水平)
- 完全兼容Element UI Table的所有功能和属性
实现原理
1. 组件结构
组件通过扩展Element UI的Table组件实现,主要包含以下核心功能:
- 监听鼠标滚轮事件,实现横向滚动
- 自动检测表格滚动条状态
- 提供可配置的提示信息
- 支持滚动方向切换
2. 核心代码实现
2.1 组件定义
import { Table } from "element-ui";
export const tableMouseHorizontalWheel = {
extends: Table,
data() {
return {
tooltipContentList: [],
tooltipVisible: this.showTooltip,
scrollDirection: 'vertical', // 默认为垂直滚动
isScrollingToEdge: false, // 是否滚动到边缘
};
},
props: {
/** @prop {Boolean} [disableMouseHorizontalWheel=false] - 是否禁用鼠标横向滚动功能 */
disableMouseHorizontalWheel: {
type: Boolean,
default: false,
},
/** @prop {Boolean} [hiddenMouseWheel=false] - 是否隐藏鼠标滚动提示 */
hiddenMouseWheel: {
type: Boolean,
default: false,
},
/** @prop {Boolean} [showTooltip=false] - 是否显示提示信息 */
showTooltip: {
type: Boolean,
default: false,
},
/** @prop {String|Array} [tooltipContent=[]] - 提示信息内容 */
tooltipContent: {
type: [String, Array],
default: () => [],
},
/** @prop {Object} [tooltipPosition={ top: "10px", left: "10px" }] - 提示信息位置 */
tooltipPosition: {
type: Object,
default: () => ({
top: "10px",
left: "10px",
})
},
}
// ... 其他代码省略
}
2.2 横向滚动实现
handleWheel(event) {
const tableBody = this.$el.querySelector(".el-table__body-wrapper");
// 当表格内容高度小于容器高度时,直接启用横向滚动
if(tableBody.scrollHeight <= tableBody.clientHeight) {
event.preventDefault();
tableBody.scrollLeft += event.deltaY;
return;
}
// 当处于水平滚动模式或按住Alt键时,启用横向滚动
if (this.scrollDirection === 'horizontal' || event.altKey) {
event.preventDefault();
tableBody.scrollLeft += event.deltaY;
}
}
2.3 滚动条检测
hasScrollbarByMff() {
const tableBody = this.$el.querySelector(".el-table__body-wrapper");
// 检测竖向滚动条
const verticalScrollbarWidth = tableBody.scrollHeight - tableBody.clientHeight;
// 检测横向滚动条
const horizontalScrollbarHeight = tableBody.scrollWidth - tableBody.clientWidth;
// 当同时存在横向和纵向滚动条时,显示提示信息
if (verticalScrollbarWidth > 0 && horizontalScrollbarHeight > 0 && !this.hiddenMouseWheel) {
this.tooltipContentList.push("按住Alt键可以横向滚动表格");
this.tooltipVisible = true;
this.$el.addEventListener("dblclick", this.toggleScrollDirection);
this.tooltipContentList.push('双击表格任意位置可切换滚动方向');
} else {
// 清除提示信息
this.tooltipContentList = this.tooltipContentList.filter(item =>
!item.includes('按住Alt键可以横向滚动表格') &&
!item.includes('双击表格任意位置可切换滚动方向')
);
this.tooltipVisible = false;
}
}
2.4 全部代码
import { Table } from "element-ui";
/**
* @description 扩展Element UI Table组件,支持鼠标横向滚动和提示功能
* @extends {Table}
*/
export const tableMouseHorizontalWheel = {
extends: Table,
data() {
return {
tooltipContentList: [],
tooltipVisible: this.showTooltip,
scrollDirection: 'vertical', // 默认为垂直滚动
isScrollingToEdge: false, // 是否滚动到边缘
};
},
props: {
/** @prop {Boolean} [disableMouseHorizontalWheel=false] - 是否禁用鼠标横向滚动功能 */
disableMouseHorizontalWheel: {
type: Boolean,
default: false,
},
/** @prop {Boolean} [hiddenMouseWheel=false] - 是否隐藏鼠标滚动提示 */
hiddenMouseWheel: {
type: Boolean,
default: false,
},
/** @prop {Boolean} [showTooltip=false] - 是否显示提示信息 */
showTooltip: {
type: Boolean,
default: false,
},
/** @prop {String|Array} [tooltipContent=[]] - 提示信息内容 */
tooltipContent: {
type: [String, Array],
default: () => [],
},
/** @prop {Object} [tooltipPosition={ top: "10px", left: "10px" }] - 提示信息位置 */
tooltipPosition: {
type: Object,
default: () => ({
top: "10px",
left: "10px",
})
},
},
created() {
// 初始化提示信息列表
if (Array.isArray(this.tooltipContent)) {
this.tooltipContentList.push(...this.tooltipContent);
} else {
this.tooltipContentList.push(this.tooltipContent);
}
},
mounted() {
const newHasScrollbarByMff = _.debounce(this.hasScrollbarByMff, 10);
// 监听this.$el元素变化
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === "childList") {
newHasScrollbarByMff();
}
});
});
observer.observe(this.$el, {
childList: true,
subtree: true,
});
if (!this.disableMouseHorizontalWheel) {
this.$el.addEventListener("wheel", this.handleWheel);
}
},
beforeDestroy() {
if (!this.disableMouseHorizontalWheel) {
this.$el.removeEventListener("wheel", this.handleWheel);
}
},
methods: {
/**
* @description 处理鼠标滚轮事件,实现横向滚动
* @param {WheelEvent} event - 鼠标滚轮事件对象
*/
handleWheel(event) {
const tableBody = this.$el.querySelector(".el-table__body-wrapper");
// tableBody.scrollHeight <= tableBody.clientHeight
if(tableBody.scrollHeight <= tableBody.clientHeight) {
event.preventDefault();
tableBody.scrollLeft += event.deltaY;
return;
}
if (this.scrollDirection === 'horizontal' || event.altKey) {
event.preventDefault();
tableBody.scrollLeft += event.deltaY;
}
},
/**
* @description 检测表格是否同时存在横向和纵向滚动条,并显示提示信息
*/
/**
* @description 切换滚动方向
*/
toggleScrollDirection() {
this.scrollDirection = this.scrollDirection === 'vertical' ? 'horizontal' : 'vertical';
this.tooltipContentList = this.tooltipContentList.filter(item => !item.includes('当前滚动方向'));
this.tooltipContentList.push(`当前滚动方向: ${this.scrollDirection === 'vertical' ? '垂直' : '水平'}`);
// 消息提醒
this.$message({
message: `当前表格滚动方向已切换为: ${this.scrollDirection ==='vertical'? '垂直' : '水平'}`,
type: 'info',
duration: 1000,
})
},
/**
* @description 显示边缘视觉反馈
* @param {HTMLElement} element - 需要添加视觉反馈的元素
*/
showEdgeFeedback(element) {
if (!this.isScrollingToEdge) {
this.isScrollingToEdge = true;
element.style.transition = 'background-color 0.3s';
element.style.backgroundColor = 'rgba(0, 0, 0, 0.1)';
setTimeout(() => {
element.style.backgroundColor = '';
setTimeout(() => {
element.style.transition = '';
this.isScrollingToEdge = false;
}, 300);
}, 300);
}
},
hasScrollbarByMff() {
console.log(123);
const tableBody = this.$el.querySelector(".el-table__body-wrapper");
// 是否有竖向滚动条
const verticalScrollbarWidth =
tableBody.scrollHeight - tableBody.clientHeight;
console.log(tableBody.scrollHeight, tableBody.clientHeight,'1231321321',verticalScrollbarWidth);
// 是否有横向滚动条
const horizontalScrollbarHeight =
tableBody.scrollWidth - tableBody.clientWidth;
console.log(tableBody.scrollWidth, tableBody.clientWidth,'1231321321',horizontalScrollbarHeight);
// 如果有横向滚动条和竖向滚动条 hiddenMouseWheel 为false时 tooltipVisible 为true
if (
verticalScrollbarWidth > 0 &&
horizontalScrollbarHeight > 0 &&
!this.hiddenMouseWheel
) {
this.tooltipContentList.push("按住Alt键可以横向滚动表格");
this.tooltipVisible = true;
this.$el.addEventListener("dblclick", this.toggleScrollDirection);
this.tooltipContentList.push('双击表格任意位置可切换滚动方向')
}else{
this.tooltipContentList = this.tooltipContentList.filter(item =>!item.includes('按住Alt键可以横向滚动表格'));
this.tooltipContentList = this.tooltipContentList.filter(item =>!item.includes('双击表格任意位置可切换滚动方向'));
this.tooltipVisible = false;
console.log(1231321);
}
},
},
render(h) {
const table = this.$options.extends.render.call(this, h);
return (
<div
style={{
position: "relative",
}}
>
<el-tooltip
placement="top"
style={{
position: "absolute",
...(this.tooltipPosition.top && { top: this.tooltipPosition.top }),
...(this.tooltipPosition.left && { left: this.tooltipPosition.left }),
...(this.tooltipPosition.bottom && { bottom: this.tooltipPosition.bottom }),
...(this.tooltipPosition.right && { right: this.tooltipPosition.right }),
zIndex: 11,
display: this.tooltipVisible ? "block" : "none",
}}
>
<div slot="content">
{this.tooltipContentList.map((item, index) => {
return (
<div key={index} style={{ marginBottom: "4px" }}>
<span>{index + 1}.</span> {item}
</div>
);
})}
</div>
<i
class="el-icon-info"
style={{
cursor: "pointer",
display: this.tooltipVisible ? "block" : "none",
}}
></i>
</el-tooltip>
{table}
</div>
);
},
}
使用示例
1. 注册组件
import Vue from "vue";
import { tableMouseHorizontalWheel } from "@/components/EllTable/index";
Vue.component("ell-table", tableMouseHorizontalWheel);
2. 基础用法
<template>
<div>
<ell-table :data="tableData" border style="width: 100%" height="400">
<el-table-column
prop="date"
label="日期"
width="180"
fixed="left"
></el-table-column>
<el-table-column label="合并列" width="660">
<el-table-column prop="name" label="姓名" width="180"></el-table-column>
<el-table-column
prop="nickname"
label="昵称"
width="180"
></el-table-column>
<el-table-column
prop="address"
label="地址"
width="300"
></el-table-column>
</el-table-column>
<!-- 更多列配置 -->
</ell-table>
</div>
</template>
配置说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| disableMouseHorizontalWheel | 是否禁用鼠标横向滚动功能 | Boolean | false |
| hiddenMouseWheel | 是否隐藏鼠标滚动提示 | Boolean | false |
| showTooltip | 是否显示提示信息 | Boolean | false |
| tooltipContent | 提示信息内容 | String/Array | [] |
| tooltipPosition | 提示信息位置 | Object | { top: "10px", left: "10px" } |
注意事项
- 组件会自动检测表格是否同时存在横向和纵向滚动条,如果存在则显示提示信息
- 可以通过
disableMouseHorizontalWheel属性禁用鼠标横向滚动功能 - 提示信息位置可以通过
tooltipPosition属性灵活配置 - 双击表格可以切换滚动方向(垂直/水平)
- 按住Alt键可以临时启用横向滚动
- 组件完全兼容Element UI Table的所有功能,可以正常使用Table组件的所有属性和方法
总结
通过扩展Element UI的Table组件,我们实现了一个更加便捷的表格组件,支持鼠标横向滚动和智能提示功能。这个组件不仅提升了用户体验,还保持了与原有Table组件的完全兼容性。在实际项目中,这个组件可以有效提升表格数据的浏览效率,特别是在处理大量列数据时。