近期接到一个需求,需要实现一个动态表格,并使表格的列支持拖拽伸缩。在初步调研时,发现官方文档中已有相关案例,但一上手实现后却遇到了许多 bug,导致功能无法正常使用。查阅相关博客,也是找到了对应的解决方案。谨以此文记录下本次的踩坑过程,分享解决方案与优化思路。
目录
一、效果图

二、遇到的相关问题解决
1 拖拽不生效问题
解决方案:变更 vue-draggable-resizable 的版本号为:V2.1.0
npm install --save vue-draggable-resizable@2.1.0
2 限制表格宽度
解决方案:添加滚动属性:
<a-table
...
:scroll="{ x: scrollX }"
...
>
...
</a-table>
还需要动态计算该字段,避免列宽拖动,而滚动条实际长度未产生变化的问题。
computed: {
// 动态获取scrollX,防止数组固定列的大小变化
scrollX () {
return this.columns.reduce((preVal, curVal) => {
return preVal + curVal.width
}, 0)
}
},
3 限制表格最小及最大宽度。
解决方案:于初始化拖拽事件中限制,主体逻辑如下:
initDrag (columns) {
const historyMap = new Map()
...
const resizeableTitle = (h, props, children) => {
let deltaX = 0
...
const { key, ...restProps } = props
const col = columns.find((col) => {
const k = col.dataIndex || col.key
return k === key
})
...
const onDrag = (x) => {
// 在拖拽过程中计算基于初始位置的偏移量
let calculateX = 0
const historyX = historyMap.get(key) || 0
deltaX = historyX && historyX - x
if (historyX && col.width === this.threshold.max) {
// 场景一:拖拽超出最大值
if (historyX > x) calculateX = col.width - deltaX
else calculateX = col.width
} else if (historyX && col.width === this.threshold.min) {
// 场景二:拖拽超出最小值
if (historyX < x) calculateX = col.width - deltaX
else calculateX = col.width
} else {
// 场景三:区间范围内
calculateX = col.width - deltaX
}
...
let width = Math.max(calculateX, this.threshold.min)
width = Math.min(width, this.threshold.max)
col.width = width
historyMap.set(key, x)
}
const onDragstop = (x) => {
historyMap.set(key, x)
...
}
return (
<th
{...restProps}
v-ant-ref={(r) => (thDom = r)}
width={draggingState[key]}
class="resize-table-th"
>
{children}
<vue-draggable-resizable
...
x={col.width || draggingState[key]}
...
draggable={true}
...
onDragging={onDrag}
onDragstop={onDragstop}
></vue-draggable-resizable>
</th>
)
}
this.components = {
header: {
cell: resizeableTitle
}
}
},
4 限制某些列不可伸缩。
解决方案:判定绑定dataIndex字段,返回原dom
initDrag (columns) {
...
const resizeableTitle = (h, props, children) => {
...
const { key, ...restProps } = props
const col = columns.find((col) => {
const k = col.dataIndex || col.key
return k === key
})
// action || serial 限制操作列不可伸缩
if (!col.width || col.dataIndex === 'action' || col.dataIndex === 'serial') {
return <th {...restProps}>{children}</th>
}
...
return (
...
)
}
this.components = {
header: {
cell: resizeableTitle
}
}
},
上述问题所参考的博客:
三、组件封装
解决上述问题功能已经处于可用状态,但需要用于多处表格页面,故而进行了封装。
主要考虑了以下几点:
1 表格字段存在格式化、枚举值映射及其余特殊操作。
解决方案:使用插槽的动态传入组件:
父组件:
<template>
<div>
...
<scalable-column ... :slotList="slotList">
<template v-slot:serial="{ text, record, index }">
{
{ query.pageSize * (query.pageNum - 1) + index + 1 }}
</template>
<template v-slot:action="{ record }">
<a @click="handleDetail(record)">详情</a>
</template>
</scalable-column>
...
</div>
</template>
<script>
import ScalableColumn from '@/components/Table/ScalableColumn.vue'
export default {
components: {
ScalableColumn
},
data () {
return {
...
query: {
pageSize: 10,
pageNum: 1
},
slotList: [
{ name: 'action' },
{ name: 'serial' }
],
...
}
},
methods: {
handleDetail (record) {
...
}
}
}
<

最低0.47元/天 解锁文章
1641

被折叠的 条评论
为什么被折叠?



