最近项目中遇到一个需求,文字太多时需要展开与折叠,一开始我使用了antdesign vue中的Typography 组件,但是我发现,这个组件展开之后没有办法折叠,搜索了很多都没找到方法,于是参考这篇文章成功自己封装了一个组件,另外增加了复制功能。
<template>
<div v-show="props.content">
<p :class="[expanded ? 'ellipsis' : '', 'text-content']" ref="textContentRef">
{{ props.content }}
</p>
<a-button v-if="isOverflowing" size="small" type="link" @click="expanded = !expanded">{{ expanded ? '收起' : '展开'
}}</a-button>
<a-button type="link" size="small" @click="copy(props.content)">复制</a-button>
</div>
</template>
<script setup>
import { ref, defineProps, nextTick, watch } from 'vue';
import { message } from 'ant-design-vue';
import { useClipboard } from '@vueuse/core'
const props = defineProps(['content'])
const expanded = ref(false)
// isOverflowing:用来判断文本是否超出了 5 行
const isOverflowing = ref(false)
const textContentRef = ref()
// 计算是否溢出 1 行
const calculateOverflow = () => {
const el = textContentRef.value
if (el) {
const lineHeight = parseFloat(window.getComputedStyle(el).lineHeight) // 获取行高
const maxVisibleHeight = lineHeight * 1 // 计算出 1 行的最大高度
// scrollHeight:内容的实际高度(包含不可见部分)
isOverflowing.value = el.scrollHeight > maxVisibleHeight // 判断是否超出 1 行
}
}
const copy = (content) => {
const { copy } = useClipboard({ legacy: true })
copy(content)
message.success('复制成功');
}
watch(() => props.content, () => {
nextTick(() => {
calculateOverflow()
})
})
</script>
<style scoped>
p {
color: #000;
margin: 0;
word-break: break-all;
line-height: 1.5;
}
.text-content {
overflow: hidden;
display: -webkit-box;
/* 需要这行以启用多行省略号 */
-webkit-box-orient: vertical;
/* 垂直排列 */
-webkit-line-clamp: 1;
/* 限制为 1 行 */
max-height: calc(1 * 1.5em);
/* 1 行的最大高度 */
}
.text-content.ellipsis {
max-height: none;
/* 展开时显示所有内容 */
-webkit-line-clamp: unset;
/* 移除行数限制 */
}
.ant-btn-link {
padding-left: 0;
}
</style>