需求是这样的:
按照官网,table组件的border属性,设置为true时可以显示边框。有了边框才能拖。
但是显示了边框,与之前的需求相悖。同时,既然显示边框有属性border支持,那么动态的更新border的值,应该就可以实现显示表格边框的动态切换。
基于此思路,采用比较折中的办法:
鼠标移动时,通过监控鼠标事件,动态的更新border属性的值,进而动态切换边框的显示。
<el-table
:data="tableData"
:border="showBorder"
@selection-change="handleSelectionChange"
>
...
export default {
data () {
return {
showBorder: false
}
}
}
...
...
methods: {
// 要在表格渲染出来后再加
addListener () {
const tabHeader = this.$el.querySelector('.el-table__header-wrapper')
if (tabHeader) {
tabHeader.onmouseenter = this.updataTableBorder.bind(this, true)
tabHeader.onmouseleave= this.updataTableBorder.bind(this, false)
}
},
updataTableBorder (value) {
this.showBorder = value
}
}
...
到这里,功能已经实现了,当鼠标移动到表头时,边框显示,然后就可以拖动列。鼠标从表头移开,切换的无边框状态。
如果只是这么操作,会发现切换时,表格会抖动。体验感非常的不好。
之所以会抖动,是因为不显示边框时,boder的width值为0,在切换到显示边框时,边框有了实际的宽度,会占位置,导致表格相对无边框时出现位置偏移。
如何让边框切换时,不抖动呢?
方案:
先给表格加上边框,
对比切换前后的表格样式,发现边框样式,涉及到以下三个地方。
另外,element-ui的table组件,有三个属性,刚好可以控制表格、表头单元格和所有单元格的样式。分别是
cell-style属性时配置所有单元格的样式(包括表头),header-cell-style只控制表头的单元格样式。如果你没有另外配置header-cell-style,完全可以用cell-style来控制所有单元格的边框。
那么,给style、header-cell-style、cell-style属性,分别绑定tableStyle、headerCellStyle、cellStyle等三个变量,动态的更新这三个值,依照Vue的响应式原理,对应的style、header-cell-style、cell-style属性值将会随之改变。
<el-table
:data="tableData"
:border="showBorder"
:style="tableStyle"
:header-cell-style="headerCellStyle"
:cell-style="cellStyle"
@selection-change="handleSelectionChange"
>
const noBordertyle = '1px solid transparent'
const borderStyle = '1px solid #EBEEF5'
export default {
data () {
return {
showBorder: false,
// 表格样式
tableStyle: {
borderTop: noBordertyle,
borderLeft: noBordertyle
},
// 表头样式
headerCellStyle: {
background: 'rgba(42,113,255,0.03)',
color: '#000000',
borderBottom: noBordertyle,
borderRight: noBordertyle
},
// 单元格样式
cellStyle: {
borderBottom: noBordertyle,
borderRight: noBordertyle
}
}
},
methods: {
// 要在表格渲染出来后再加
addListener () {
const tabHeader = this.$el.querySelector('.el-table__header-wrapper')
if (tabHeader) {
tabHeader.onmouseenter = this.updataTableBorder.bind(this, true)
tabHeader.onmouseleave= this.updataTableBorder.bind(this, false)
}
},
updataTableBorder (open) {
this.showBorder = open
const border = open ? borderStyle : noBordertyle
this.tableStyle.borderTop = border
this.tableStyle.borderLeft = border
this.headerCellStyle.borderBottom = border
this.headerCellStyle.borderRight = border
this.cellStyle.borderBottom = border
this.cellStyle.borderRight = border
}
}
}
问题虽然得到了解决,但是,通常在项目中,会有很多地方用到表格,表格的风格一般都是一致的。
如果按上述过程直接用,那么在每个使用表格的组件中,都要加入处理这些代码。处理维护起来,那是相当的繁琐。
如果能把这些处理过程,放到一个地方单独维护,那就舒服多了。
想到Vue的 mixin 混入了吧。
import mixin from ''./mixins/tableMixin
export default {
...
mixins: [mixin]
}
完!!!
按之前的处理完成后,表格确实不抖动了。但仔细观察后发现,位于表格最后一列的操作列,左边的边框没显示。而是只是差了1个像素没显示。
反复检查单元格的边框样式,都是正常的。也就是正常情况下应该会显示,而实际就是没有。百思不得其解。
转天再看这个问题,发现最后的操作列使用了fixed属性,为固定列。也就是当使用横向滚动条拖动时,最后的操作列位置是不变的。
仔细检查固定列,查看DOM结构,发现多了一个 el-table__fixed-right 的div,样式使用了绝对定位,并且在内联样式中设置了宽度width。而且这家节点刚好对应右侧的操作列。
那么是不是这个div,覆盖在本该显示的边框元素之上,由于我用非常规手段,修改了边框,导致这个绝对定位的元素,width值已不准确,进而边框被覆盖。
手动调整固定列的列宽,去掉1个像素。果然边框出现了。
既然找到症结,解决问题也就简单了。在addListener方法中,把这个div的宽度减1就OK了。
addListener () {
const tabHeader = this.$el.querySelector('.el-table__header-wrapper')
if (tabHeader) {
tabHeader.onmouseenter = this.updataTableBorder.bind(this, true)
tabHeader.onmouseleave= this.updataTableBorder.bind(this, false)
}
const fixedRightNode = this.$el.querySelector('.el-table__fixed-right')
if (fixedRightNode) {
const width = fixedRightNode.style.width
fixedRightNode.style.width = width ? (parseInt(width) - 1) + 'px' : width
}
},