需求:当人员数量超过第2行时,显示省略号,并在结尾展示“等x人”
如果只是需要省略号,那么直接给父元素添加如下css即可。
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
这种方式很简单,缺点也明显,就是末尾只能展示...,不能改成其他内容。因此,要满足需求,就需要我们手动计算两行可容纳的实际数量。
实现思路:
获取父元素的宽度,再获取所有人名元素的宽度,逐行计算每行能够容纳的最大数量(单个人名不能分割到第二行),再进行累加,两行能够容下的最大数量,当实际数量超出能容纳的范围时,则在末尾显示'...等x人'
实现代码如下(基于vue3): 在线演示
<script setup>
import { ref, nextTick } from 'vue'
const nameList = ref([])
const nameCount = ref(0)
const setNameCount = (result) => {
nameCount.value = result
}
const addName = () => {
nameList.value = [
"John",
"Mary",
"David",
"Sarah",
"Michael",
"Emily",
"James",
"Emma",
"Andrew",
"Olivia",
"Daniel",
"Sophia",
"Matthew",
"Ava",
"Christopher",
"Isabella",
"William",
"Grace",
"Alexander",
"Chloe"
];
}
const sliceName = (list) => {
const count = nameCount.value;
if (count === 0 || list.length <= count) {
return list;
}
return list.slice(0, count);
}
const vLineCount = {
mounted(el, binding, vnode, prevVnode) {
nextTick(() => {
const containerWidth = el.clientWidth
console.log()
const nameSpan = el.querySelectorAll('.name')
let spanWidthList = []
let elementCount
if (nameSpan && nameSpan.length > 0) {
if (nameSpan && nameSpan.length > 0) {
spanWidthList = Array.from(nameSpan).map(item => item.offsetWidth + 2)
}
elementCount = calculateElements(spanWidthList, containerWidth, 2);
if (elementCount < spanWidthList.length) {
elementCount = calculateElements(spanWidthList, containerWidth, 2, 60);
}
}
setNameCount(elementCount)
function calculateElements(widths, containerWidth, rowCount, reduction = 0) {
let totalWidth = 0;
let elementCount = 0;
let rowIndex = 0;
for (let i = 0; i < widths.length; i++) {
if (totalWidth + widths[i] <= containerWidth - (rowIndex >= rowCount - 1 ? reduction : 0) && rowIndex < rowCount) {
totalWidth += widths[i];
elementCount++;
} else {
totalWidth = widths[i];
rowIndex++;
if (rowIndex >= rowCount) {
break;
}
elementCount++;
}
}
return elementCount;
}
})
},
}
</script>
<template>
<span
v-if="nameList.length > 0"
v-line-count
class="ellipsis-two-lines"
>
<span
v-for="(item, index) in sliceName(nameList)"
:key="index"
class="name"
>{{ item }}</span>
<span v-show="nameList.length > nameCount">...等{{ nameList.length }}人</span>
</span>
<button @click="addName">
添加人
</button>
</template>
<style>
.ellipsis-two-lines {
border: 1px solid red;
width: 300px;
display: flex;
flex-wrap: wrap;
}
.name {
display: inline-block;
padding: 0 5px;
border: 1px solid red;
margin-right: 2px;
}
.cell-custom {
border: 1px solid red;
}
</style>