前言
最近做移动端的h5项目,要做一个可配置表头的复杂表格,网上找了很久也没什么好方法,结合网上的一些例子,在此做一了一个完整的vue版的例子。
效果
无图无真相,先上最终效果图再说 。
方法一:iscroll 插件版
第一步:npm install
引入 iscroll
npm i iscroll --save
第二步:封装
对插件再做一层封装,封装成 iscrollTable.js 方便调用,代码如下:
// 统一使用
const iScollProbe = require('iscroll/build/iscroll-probe');
let scroller = null;
let Selector = "";
export function createIScroller(selector) {
Selector = selector;
scroller = new iScollProbe(Selector, {
preventDefault: false, // 阻止浏览器滑动默认行为
probeType: 3, //需要使用 iscroll-probe.js 才能生效 probeType : 1 滚动不繁忙的时候触发 probeType : 2 滚动时每隔一定时间触发 probeType : 3 每滚动一像素触发一次
mouseWheel: true, //是否监听鼠标滚轮事件。
scrollX: true, // 启动x轴滑动
scrollY: true, // 启动y轴滑动
// momentum: false,
lockDirection: false,
snap: false, //自动分割容器,用于制作走马灯效果等。Options.snap:true// 根据容器尺寸自动分割
//snapSpeed: 400,
scrollbars: false, //是否显示默认滚动条
freeScroll: true, //主要在上下左右滚动都生效时使用,可以向任意方向滚动。
deceleration: 0.0001, //滚动动量减速越大越快,建议不大于 0.01,默认:0.0006
disableMouse: true, //是否关闭鼠标事件探测。如知道运行在哪个平台,可以开启它来加速。
disablePointer: true, //是否关闭指针事件探测。如知道运行在哪个平台,可以开启它来加速。
disableTouch: false, //是否关闭触摸事件探测。如知道运行在哪个平台,可以开启它来加速。
eventPassthrough: false, //使用 IScroll 的横轴滚动时,如想使用系统立轴滚动并在横轴上生效,请开启。
bounce: false //是否启用弹力动画效果,关掉可以加速
});
scroller.on('scroll', updatePosition);
scroller.on('scrollEnd', updatePosition);
scroller.on('beforeScrollStart', function () {
scroller.refresh();
});
function updatePosition() {
let frozenCols = document.querySelectorAll(selector + ' table tr td.cols');
let frozenRows = document.querySelectorAll(selector + ' table tr th.rows');
let frozenCrosses = document.querySelectorAll(selector + ' table tr th.cross');
for (let i = 0; i < frozenCols.length; i++) {
frozenCols[i].style.transform = 'translate(' + -1 * this.x + 'px, 0px) translateZ(0px)';
}
for (let i = 0; i < frozenRows.length; i++) {
frozenRows[i].style.transform = 'translate(0px, ' + -1 * this.y + 'px) translateZ(0px)';
}
for (let i = 0; i < frozenCrosses.length; i++) {
frozenCrosses[i].style.transform = 'translate(' + -1 * this.x + 'px,' + -1 * this.y + 'px) translateZ(0px)';
}
}
return scroller;
}
export function refreshScroller() {
if (scroller === null) {
console.error("先初始化scroller");
return;
}
setTimeout(() => {
scroller.refresh();
scroller.scrollTo(0, 0);
let frozenCols = document.querySelectorAll(Selector + ' table tr td.cols');
let frozenRows = document.querySelectorAll(Selector + ' table tr th.rows');
let frozenCrosses = document.querySelectorAll(Selector + ' table tr th.cross');
for (let i = 0; i < frozenCols.length; i++) {
frozenCols[i].style.transform = 'translate(0px, 0px) translateZ(0px)';
}
for (let i = 0; i < frozenRows.length; i++) {
frozenRows[i].style.transform = 'translate(0px, 0px) translateZ(0px)';
}
for (let i = 0; i < frozenCrosses.length; i++) {
frozenCrosses[i].style.transform = 'translate(0px, 0px) translateZ(0px)';
}
}, 0);
}
第三步:使用
引用前面的自己封装的iscrollTable.js,用到的table.vue的具体代码如下:
{{l.name}}
{{ yList[i][yKey]}}
注意点:
- table 外的盒子 .rolling-table 要设置高度,不然向上滚动失效
2.固定和行与列,即:rows、cross 的position要设为relative
最终效果就如上图。
方法二: 结合css,自定义封装版
原理
因为除了表头和第一列,其他都可以滚动所以需要:
1.一个展示的table表格
2.一个用来覆盖上表头的 thead,一个用来覆盖左上角的 div,一个固定在第一列的 tbody。
- 展示的table表格放在最底层,覆盖上表头的 thead固定定位在最上面,固定在第一列的 tbody固定定位在最左边,左上角的 div固定是左上角且z-index最大,在最上层。
- 固定的表格头部与第一列的宽、高、行高都是通过获取真实的表格的宽高来设定的。
- 通过展示的table表格的上下滚动从而带动固定在第一列的 tbody向上滚动,向左右滚动带动覆盖上表头的 thead的左右滚动。
完整代码如下:
{{l.name}}
{{xList[0][0].name}}
{{l.statis_date }}
{{l.name}}
{{ yList[i][yKey]}}
最终效果图如下:
不过这个版本的上下滚动时的精准计算有点误差。
推荐第一种方式。
最后
希望文章内容对你有一点帮助!
对 全栈开发 有兴趣的朋友可以扫下方二维码关注我的公众号 —— 爱写bugger的阿拉斯加
分享 web 开发相关的技术文章,热点资源,全栈程序员的成长之路。
大家一起交流成长。
只要关注公众号并回复 福利 便送你六套、并且每套价值 3999 元的视频资源: Python、Java、Linux、Go、vue、react、javaScript