前端小白记录自己需求中奇奇怪怪的表格
最近遇到的一个需求,需要绘制表格第一个表头的对角线。在网上搜了很多资料,都达不到自己的要求,于是在自己的一通骚操作下,终于实现此功能,具体方案记录如下:
效果图
具体思路:
对角线直接采用定位加旋转的方法,旋转原点为表格左上角。第一个表头使用 slot=“header”插槽,使用两个标签加样式将文字分开。
HTML代码结构:
<div class="tableBox">
<el-table :data="listData" border class="tableArea" style="width: 100%">
<el-table-column
prop="productType"
align="center"
min-width="1"
>
<template slot="header">
<div style="display: flex; justify-content: space-between;">
<span>商品</span><span>类别</span>
</div>
</template>
</el-table-column>
...
</el-table>
<div class="diagonal"></div>
</div>
CSS代码:
.tableBox {
position: relative;
}
.diagonal {
position: absolute;
top: 0;
left: 0;
height: 1px;
width: 268px;
background-color: black;
transform-origin: left;
transform: rotate(10deg);
}
做到这个时候感觉好像已经结束,接着就发现大bug啦,因为表格的列宽采用min-width按比例分配的,所以在不同的屏幕上列宽也不同,以上代码对角线的长度与角度直接写死,在不同的屏幕上可能出现问题,所以对角线的宽度与旋转角度需要自动计算,动态绑定,更改后的代码方案如下:
**主要思路:**使用element Table里的api,获取第一个单元格的dom元素,得到对角线相应的宽高,使用Math数学对象计算对角线的长度与正切值。
HTML部分(主要改动为给table添加header-cell-style的回调方法与动态绑定对角线的行间样式):
<el-table
:data="listData"
border
class="tableArea"
style="width: 100%"
:header-cell-style = "handleHeaderCell"
>
</el-table>
...
<div
class="diagonal"
:style="{
width:diagonalWidth+'px',
transform:'rotate('+diagonalAngel+'deg)'
}"
>
</div>
...
JS部分:
<script>
export default {
data() {
return {
listData: [],
//第一个单元格的类名
headerCellClassName:'',
//第一个单元格的宽度
headerCellOffsetWidth:0,
//第一个单元格的高度
headerCellOffsetHeight:0,
//对角线旋转的角度
diagonalAngel:0,
//对角线的长度
diagonalWidth:0
};
},
methods: {
// 获取数据
queryData() {
this.listData = [
{
id: "201808300001",
productType: "纺织品",
amount: 20,
productName: "上衣",
price: "80",
updateTime: "2018-08-30",
},{
id: "201808300002",
productType: "纺织品",
amount: 20,
productName: "裤子",
price: "76",
updateTime: "2018-08-31",
},{
id: "201808300003",
productType: "皮制品",
amount: 100,
productName: "挎包",
price: "150",
updateTime: "2018-08-31",
},
];
},
handleHeaderCell({row,column,rowIndex,columnIndex}){
console.log(row[0].id);
var _this = this;
_this.headerCellClassName= row[0].id
this.$nextTick(()=>{
_this.getDiagonal();
})
},
getDiagonal(){
var _this = this;
//获取第一个单元格DOM元素
let oHeaderCell = document.getElementsByClassName(_this.headerCellClassName)[0];
//通过一个单元格的宽高,确定对角线的长度与正切值。
_this.headerCellOffsetWidth = oHeaderCell.offsetWidth;
_this.headerCellOffsetHeight = oHeaderCell.offsetHeight;
_this.diagonalWidth = Math.sqrt(
Math.pow(_this.headerCellOffsetWidth,2)+Math.pow(_this.headerCellOffsetHeight,2)
);
_this.diagonalAngel = Math.atan(
_this.headerCellOffsetHeight/_this.headerCellOffsetWidth
)*180/Math.PI;
}
},
mounted() {
this.queryData();
},
};
</script>
以上基本已经实现对角线的绘制,最后的细节就是,当window窗口动态变化时,需要刷新页面才能将对角线的角度与长度更新过来,应该是nextTick只会触发一次(异步渲染),需要使用watch监听视口变化,每次变化时重新调用函数getDiagonal();vue监听窗口的变化参考星期五の夜博客,链接:[https://blog.csdn.net/weixin_43550562/article/details/104589191]。
JS代码改动如下:
export default {
data() {
return {
...
screenWidth: document.body.clientWidth,
timer: null
...
};
},
methods: {
...
},
mounted() {
this.queryData();
let _this = this;
//mounted里挂载window.onresize事件
window.onresize = () => {
return (() => {
window.screenWidth = document.body.clientWidth
_this.screenWidth = window.screenWidth
})()
}
},
watch:{
//监听window窗口的变化,执行getDiagonal()方法,更新对角线的角度与长度。
screenWidth(val){
let _this = this
if (!_this.timer) {
// 一旦监听到的screenWidth值改变,就将其重新赋给data里的screenWidth
_this.screenWidth = val
_this.timer = true
setTimeout(function() {
_this.getDiagonal();
_this.timer = false
}, 400)
}
}
}
};
最后为了实现表头的对角线,这一堆的骚操作我也很无奈,大家有更好的方法与提议欢迎留言。