大家好,我是前端小喵
一、背景:
vue3项目要实现动态文本多行超出省略,并且有查看全部功能、收起全部功能;
之前因为文案是前端本地写死的而且一行要展示的内容是固定的,所以用数组分行实现了
但后端返回动态文案string,且随着屏幕resize,每行展示内容也会变化
二、解决思路
1.默认展示内容,配上normal类名(css 溢出...效果、弹性伸缩盒子模型),props hiddenLineNum 控制在一个块元素显示的文本的行数
2.挂载完成后,通过ref获取dom的scrollHeight、offsetHeight,如果scrollHeight>offsetHeight,则为溢出展示查看全部按钮
offsetHeight:元素的像素高度 包含元素的padding和border
scrollHeight:元素内容的高度,包括溢出的不可见内容,offsetHeight即是自身的高度,scrollHeight是自身的高度+隐藏元素的高度
3.查看按钮、收起全部 动态类名(.all)控制是否全部展示文本,去除省略...效果
4.挂载完成后添加resize的事件refresh,组件卸载之前移除refresh事件
三、具体代码
// show-more-text.vue
<template>
<div
:class="{ all: !isShowAll }"
class="normal"
:style="{ '-webkit-line-clamp': hiddenLineNum }"
ref="textRef"
>
<span>
{{ value }}
</span>
</div>
<span v-if="isShowMore && value" class="operationTextColor" @click="switchAll">
{{ isShowAll ? '查看全部' : '收起全部' }}
</span>
</template>
<script setup>
import { onBeforeUnmount, onMounted, ref } from 'vue'
const props = defineProps({
value: {
type: String || Number,
default: ''
},
hiddenLineNum: {
type: String || Number,
default: 4
}
})
const isShowMore = ref(false)
const textRef = ref('')
const isShowAll = ref(true)
const switchAll = () => {
isShowAll.value = !isShowAll.value
}
const refresh = () => {
const scrollHeight = textRef.value?.scrollHeight
const offsetHeight = textRef.value?.offsetHeight
// console.log(textRef.value, scrollHeight, offsetHeight, 666)
isShowMore.value = scrollHeight > offsetHeight
}
onMounted(() => {
refresh()
window.addEventListener('resize', refresh)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', refresh)
})
</script>
<style lang="scss" scoped>
.normal {
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
}
.all {
display: block;
text-overflow: initial;
}
</style>
四、项目使用
<show-more-text :value="companyProfile" hiddenLineNum="6"></show-more-text>