hook函数封装
export const useTableColumnWidth = _this => {
const { refTable } = _this
const columnWidthObj = ref()
const getTableColumnWidth = cb => {
nextTick(() => {
columnWidthObj.value = {}
const tableEle = refTable?.refBaseTable?.$el
if (!tableEle) return
const rows = tableEle.querySelectorAll(
'.el-table__body-wrapper .el-table__row'
)
if (!rows.length) return
const hideRows = tableEle.querySelectorAll('.hidden-columns div')
const cells = rows[0].cells
Array.from(cells).forEach((cell, i) => {
let maxVal = 0
const prop = hideRows[i].getAttribute('data-prop')
if (!prop) return
Array.from(rows).forEach(row => {
const cellsEle = row.cells[i]
cellsEle.style.display = 'inline-block'
cellsEle.style.width = '100vw'
const cellEle = cellsEle.querySelector('.cell')
cellEle.style.display = 'inline-block'
maxVal = Math.max(
cellEle.getBoundingClientRect().width + 1,
maxVal
)
cellsEle.style.display = 'table-cell'
cellsEle.style.width = 'auto'
cellEle.style.display = 'block'
})
columnWidthObj.value[prop] = Math.ceil(maxVal)
})
cb(columnWidthObj.value)
})
}
return {
columnWidthObj,
getTableColumnWidth
}
}
自定义组件封装
- BaseTable
<template>
<el-table
ref="refBaseTable"
class="dy-list-table"
element-loading-background="rgba(0, 0, 0, 0.8)"
:stripe="stripe"
border
:height="height"
:="$attrs"
>
<slot />
</el-table>
</template>
<script setup>
defineProps({
height: {
type: String,
default: '100%'
},
stripe: {
type: Boolean,
default: true
}
})
const refBaseTable = ref(null)
defineExpose({
refBaseTable
})
</script>
- TableColumn
<template>
<el-table-column
v-if="hasDefaultSlot"
:min-width="getMinWidth()"
:width="cWidth"
:data-prop="dataProp"
:="$attrs"
>
<template #default="scope">
<slot v-bind="scope" />
</template>
</el-table-column>
<el-table-column
v-else
:min-width="getMinWidth()"
:width="cWidth"
:data-prop="dataProp"
:="$attrs"
/>
</template>
<script setup>
const props = defineProps({
dataProp: {
type: String,
default: ''
},
width: {
type: [String, Number],
default: ''
}
})
const $attrs = useAttrs()
const slots = useSlots()
const cWidth = ref(props.width)
const hasDefaultSlot = computed(() => !!slots.default)
const getMinWidth = () => {
const minWidth = g_utils.calcTextWidth($attrs.label)
let actualWidth = $attrs['column-width']
? Math.max(minWidth, $attrs['column-width'])
: minWidth
if ($attrs['show-overflow-tooltip'] !== undefined) {
actualWidth += 2
}
if ($attrs['column-type'] === 'width') {
cWidth.value = actualWidth + 10
return ''
} else {
if ($attrs.sortable !== undefined) actualWidth += 24
return actualWidth
}
}
</script>
- 动态计算文本的宽度
export const calcTextWidth = (
str = '',
style = {
fontSize: '16px',
fontWeight: 'bold'
}
) => {
const span = document.createElement('span')
span.innerText = str
span.style.fontSize = style.fontSize
span.style.fontWeight = style.fontWeight
document.body.appendChild(span)
const width = span.getBoundingClientRect().width + 25
document.body.removeChild(span)
return Math.ceil(width)
}
使用教程
<BaseTable
ref="refContentTable"
v-loading="loading"
:data="tableData"
row-key="imei"
style="margin-top: 10px"
>
<TableColumn
align="center"
prop="imei"
data-prop="imei"
:label="$t('public.IMEI')"
:column-width="columnWidthObj.imei"
/>
</BaseTable>
<script setup>
const loading = ref(false)
const refContentTable = ref(null)
const tableData = ref([])
const columnWidthObj = ref({})
const getDeviceList = () => {
loading.value = true
apiDeviceList({
pageNum: pageNum.value,
pageSize: pageSize.value,
...listParams.value
})
.then(({code, data}) => {
if (code === '200' && data) {
tableData.value = data.items
useTableColumnWidth({
refTable: refContentTable.value
}).getTableColumnWidth(data => {
columnWidthObj.value = data
})
}
})
.finally(() => {
loading.value = false
})
}
onMounted(() => {
getDeviceList()
})
</script>
最终效果图
