背景
使用ant design vue table组件,通过#bodyCell="{ column, record }"定义表格行的内容模板。
<a-table
ref="tableRef"
:class="[
lineParam.tableLineHeightClass,
!tableCfg?.data?.length && state.spinning && 'empty-table'
]"
:row-selection="footShow ? rowSelection : null"
:columns="tableCfg.columns"
:data-source="tableCfg.data"
:pagination="false"
rowKey="key"
:scroll="{ x: '100%', y: autoHeight }"
@resizeColumn="handleResizeColumn"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'businessModuleList'">
<BusinessTag
v-if="record?.businessModuleNameList?.length"
:tags="record?.businessModuleNameList"
:show-count="2"
:column-width="columnWidth"
/>
<div v-else>-</div>
</template>
<template v-if="column.key === 'name'">
.........
</template>
<template #emptyText>
<img v-if="!state.spinning" src="@/assets/no-data.svg" />
</template>
</a-table>
column: [
{
title: '姓名',
dataIndex: 'userDetail',
key: 'userDetail',
align: 'left',
fixed: 'left',
ellipsis: true,
width: 350,
resizable: true
},
{
title: '负责业务模块',
dataIndex: 'businessModuleList',
key: 'businessModuleList',
align: 'left',
ellipsis: true,
resizable: true,
width: 250
},
.........
]
BusinessTag组件
<template>
<div></div>
<div class="business-tag" v-for="(item, index) in tagsList" :key="index">
{{ item }}
</div>
<a-tooltip>
<template #title>{{ tags?.join('、') }}</template>
<div class="business-tag">
{{ tagText }}
</div>
</a-tooltip>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
const props = withDefaults(
defineProps<{
showCount?: number
tags: string[] | null
}>(),
{
//需要显示的tag数量,默认为3
showCount: 3
}
)
const tagText = computed(() => {
if (!props.tags?.length) return
const remainingTags = props.tags?.length - props.showCount
return remainingTags > 0 ? `+${remainingTags}...` : ''
})
const tagsList = computed(() => props.tags?.slice(0, props.showCount))
</script>
<style lang="less" scoped>
.business-tag {
display: inline-block;
border-radius: 2px;
width: fit-content;
height: fit-content;
color: black;
background-color: #f5f5f5;
padding: 0 5px;
margin: 2px 3px;
}
</style>
其中key为businessModuleList的列,正常效果如下:
鼠标悬浮在”+n“的tag上时,展现所有内容
当其中的tag太长,如果按照现有展现方式,将出现隐藏,导致展现内容不完整且tooltip无法查看:
探索
尝试1
取消列配置中的溢出隐藏:
{
title: '负责业务模块',
dataIndex: 'businessModuleList',
key: 'businessModuleList',
align: 'left',
ellipsis: true,
//resizable: true,
width: 250
},
表格根据列宽,出现换行效果,由于产品不希望换行,所以此方案不行。
尝试2
取消溢出隐藏,并将businessTag组件html部分,外面再包了一层div,并添加display: inline-block
<template>
<div style="display: inline-block">
<div class="business-tag" v-for="(item, index) in tagsList" :key="index">
{{ item }}
</div>
<a-tooltip>
<template #title>{{ tags?.join('、') }}</template>
<div class="business-tag">
{{ tagText }}
</div>
</a-tooltip>
</div>
</template>
尝试3
重写组件,根据表格宽度决定展现几个标签,若表格宽度不够则至少展示一个标签和”+n“标签,若表格宽度足够,则展示showCount个标签和”+n“标签
思考一:如何获取内容宽度
添加ref,使用ref.value.clientWidth
<template>
<div style="display: inline-block" ref="wrapper" v-if="tags?.length">
<div class="business-tag" v-for="(item, index) in visibleTags" :key="index">
{{ item }}
</div>
<a-tooltip>
<template #title>{{ tags?.join('、') }}</template>
<div class="business-tag">
{{ truncatedTagText }}
</div>
</a-tooltip>
</div>
</template>
<script lang="ts" setup>
import { computed, ref, onMounted } from 'vue'
const props = withDefaults(
defineProps<{
showCount?: number
tags: string[]
columnWidth: number
}>(),
{
//需要显示的tag数量,默认为3
showCount: 3
}
)
const wrapper = ref(null)
const fixedShowCount = ref(props.showCount)
const visibleTags = computed(() => props.tags?.slice(0, fixedShowCount.value))
const truncatedTagText = computed(() => {
if (!props.tags?.length) return ''
const remainingTags = props.tags?.length - fixedShowCount.value
return remainingTags > 0 ? `+${remainingTags}...` : ''
})
const checkAndAdjustShowCount = () => {
if (wrapper.value) {
const containerWidth = wrapper.value.clientWidth
// 减去单元格左右padding
if (containerWidth > props.columnWidth - 24) {
fixedShowCount.value = 1
} else {
fixedShowCount.value = Math.min(props.showCount, props.tags?.length || 0)
}
}
}
onMounted(() => {
if (wrapper.value) {
checkAndAdjustShowCount()
}
})
</script>
<style lang="less" scoped>
.business-tag {
display: inline-block;
border-radius: 2px;
width: fit-content;
height: fit-content;
color: black;
background-color: #f5f5f5;
padding: 0 5px;
margin: 2px 3px;
}
</style>
<template v-if="column.key === 'businessModuleList'">
<BusinessTag
v-if="record?.businessModuleNameList?.length"
:tags="record?.businessModuleNameList"
:show-count="2"
:column-width="columnWidth"
/>
<div v-else>-</div>
</template>
onMounted(() => {
columnWidth.value = columns.find(
(column) => column.key === 'businessModuleList'
).width