在经常需要对长文本内容进行多行显示并省略的情况下,如何用Vue3封装一个灵活的组件来解决这个问题呢?
组件思路
组件应接收两个属性:一个是要显示的文本内容,另一个是希望显示的最大行数。然后根据行数限制显示文本,并在必要时显示省略号。同时,如果文本的行数超过了我们给定的行数,我们会在下方显示一个可以展开/折叠全部文本的按钮。
组件代码
现在我们开始构建MoreLinesText.vue组件:
<template>
<div style="width: 300px;">
<div :style="contentStyle" ref="textContainer">
{{ content }}
</div>
<button v-show="showExpandButton" @click="toggleExpand">
{{ isExpanded ? '收起' : '展开' }}
</button>
</div>
</template>
<script>
import { ref, onMounted, computed } from "vue";
export default {
name: "MoreLinesText",
props: {
content: {
type: String,
required: true,
},
maxLines: {
type: Number,
required: true,
},
},
setup(props) {
const isExpanded = ref(false);
const showExpandButton = ref(false);
const textContainer = ref(null);
const contentStyle = computed(() => ({
overflow: 'hidden',
textOverflow: 'ellipsis',
display: '-webkit-box',
'-webkit-box-orient': 'vertical',
'-webkit-line-clamp': isExpanded.value ? '' : props.maxLines
}));
onMounted(() => {
showExpandButton.value = textContainer.value.scrollHeight > textContainer.value.offsetHeight;
});
function toggleExpand() {
isExpanded.value = !isExpanded.value;
}
return {
isExpanded,
showExpandButton,
textContainer,
contentStyle,
toggleExpand
};
}
};
</script>
组件解析
首先,在模板部分,我们有一个包含文本内容和按钮的div,其中文本的div引用了名为textContainer的ref,它将在setup函数中定义,并用于通过DOM的scrollHeight和offsetHeight属性确定是否需要显示展开按钮。
使用计算属性contentStyle来根据是否展开动态地改变样式,实现展开和收起功能。默认情况下,我们把overflow设为hidden和text-overflow设为ellipsis来隐藏溢出文本,并用-webkit-line-clamp属性设置要显示的行数。然后当文本展开时,我们去掉-webkit-line-clamp属性,显示所有文本。
最后,我们在setup函数中,使用onMounted钩子来确定是否需要展开按钮。这是通过将textContainer元素的scrollHeight(元素内容的总高度)和offsetHeight(元素可见部分的高度)相比较来实现的。如果scrollHeight大于offsetHeight,说明元素内容的行数超过了允许的行数,因此应该显示展开按钮。
当用户点击展开按钮时,我们简单地通过更改isExpanded的ref来切换文本内容的显示状态。
总结
使用Vue3和CSS,我们可以轻松地创建一个可以折叠和展开多行文本的组件。这个组件的优点是它可以适应任何文本内容和行数限制,这使得它在处理长文本时尤为有用。