最近在用elementUI的el-table
组件开发列表,产品要求第一行、最后一行、第一列、最后一列固定,按照要求开发完成后,测试了下,发现两个问题。
问题1:固定列下方的滚动条不能滑动
此问题比较好解决,增加css样式处理即可。
.el-table .el-table__fixed {
height: auto !important;
bottom: 8px !important; //具体值是多少根据页面横向滚动条的高度进行设置
}
但是将show-summary
设置为true
时,表格尾部合计行的滚动条是显示在合计行的上方的,按上方样式设置,此时固定列的滚动条会被遮挡住,非固定列的滚动条可正常使用。
我这边最后一行固定采用的是css样式实现,而非组件自带的合计行,滚动条在最后一行的下方显示,所以采用上方样式设置,固定列的滚动条不会被遮挡,且可以正常滑动。
列表最后一行固定css方式实现代码如下:
// 最后一行固定实现
.tr-sum {
background-color: #F7F9FC;
bottom: 0;
table-layout: fixed;
position: sticky;
}
其中,tr-sum
是通过el-table
组件的row-class-name
属性给最后一行添加的类名。
问题2:有固定列时列表垂直滚动错行且卡顿
表格fixed左边或者fixed右边的时候,垂直滚动表格会出现滞缓导致视觉上错行且滚动不流畅问题。
导致问题的原因
el-table
组件内部对滚动事件做了防抖,它不会实时修改非固定列的位置 ,有几毫秒的延迟。- 滚轮事件会自动触发滚动事件,滚动事件中自动使用了behavior: 'smooth'机制,这个机制会让滚动看起来很丝滑,但会耗费更多的性能,估计浏览器处于性能考虑导致两个滚动效果不同步了。
问题解决思路
- 继承覆盖element的Table组件,并重写Table组件的bindEvents方法。
- 取消掉滚轮事件的默认行为,我们自己手写滚动
问题解决步骤
1.在项目中新建tableMismatch.js文件,写上如下代码:
// 1.让Vue.component...这段注册代码早于Vue.use(ElementUI) 2.执行 delete Table._Ctor
import Vue from 'vue';
import { Table, TableColumn } from 'element-ui';
Vue.use(Table).use(TableColumn);
delete Table._Ctor;
const { bindEvents } = Table.methods;
Object.assign(Table.methods, {
bindEvents() {
bindEvents.call(this);
this.bodyWrapper.addEventListener(
'mousewheel',
this.handleBodyMousewheel
);
},
handleBodyMousewheel(event) {
const { fixedWrapper, rightFixedWrapper } = this.$refs;
if (fixedWrapper) {
const fixedBodyWrapper = fixedWrapper.querySelector(
'.el-table__fixed-body-wrapper'
);
if (fixedBodyWrapper) {
event.preventDefault();
fixedBodyWrapper.scrollBy({
left: event.deltaX,
top: event.deltaY,
});
this.$refs.bodyWrapper.scrollBy({
left: event.deltaX,
top: event.deltaY,
});
}
}
if (rightFixedWrapper) {
const fixedBodyWrapper = rightFixedWrapper.querySelector(
'.el-table__fixed-body-wrapper'
);
if (fixedBodyWrapper) {
event.preventDefault();
fixedBodyWrapper.scrollBy({
right: event.deltaX,
top: event.deltaY,
});
this.$refs.bodyWrapper.scrollBy({
right: event.deltaX,
top: event.deltaY,
});
}
}
},
});
Vue.component(Table.name, Table);
2.在项目main.js
文件中引入import '@/utils/tableMismatch.js'
以上操作,只能解决鼠标垂直滚动非固定列时的错行卡顿问题,当鼠标垂直滚动固定列时,还是会出现固定列与非固定列错行问题。
因为上述方法只在bodyWrapper
上加了mousewheel
事件,也就是说垂直滚动非固定列才会触发mousewheel
事件,而垂直滚动固定列不会触发mousewheel
事件。
尝试在上述bindEvents
函数中获取固定列DOM从而给固定列加上mousewheel
事件,但是获取不到。
所以只能另辟蹊径,进行如下操作了。
- 在表格绘制页面加上如下代码:
data() {
return {
tableBodyWrapper: null,
};
},
mounted() {
this.$nextTick(()=> {
this.tableBodyWrapper = this.$refs.elTable.bodyWrapper;
this.tableBodyWrapper.addEventListener('scroll',this.setScrollTop);
});
},
beforeDestroy() {
this.tableBodyWrapper.removeEventListener('scroll',this.setScrollTop);
},
methods: {
setScrollTop() {
const scrollTop = this.tableBodyWrapper.scrollTop;
this.$refs.table.$refs.fixedBodyWrapper.scrollTop = scrollTop;
},
}
el-table
设置了固定列后就变成了两个表格,将非固定列的滚动高度赋值给固定列,这样保持两个表格的高度统一。
其实只要步骤3,就可以解决固定列与非固定列滚动错行问题,但是步骤3不能解决滚动卡顿问题。想要解决垂直滚动卡顿问题,还是要加上步骤1、步骤2。