如何计算文本行数,控制-webkit-line-clamp对应的CTA显隐?
实现文本超过3行时显示展开/收起按钮,不足时隐藏
需求说明
有一个用户可控的文本输入框,用户可输入空内容、单个单词或无长度限制的文本。核心需求是:判断文本是否超过3行,用-webkit-line-clamp实现超过3行时截断文本,并配置展开/收起按钮(CTA);当文本不足3行(未触发截断)时隐藏该CTA,超过3行时显示。
现有代码
模板(Vue)
<div> <div ref="information" :class="isExpanded ? 'truncate': ''"> {{ data?.information }} </div> <span v-if="isTextTruncated" @click="isExpanded = !isExpanded" > {{ toggleCtaLabel }} </span> </div>
样式
.truncate { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
脚本(Vue 3 Composition API)
const isExpanded = ref(true) const information = ref(); const isTextTruncated = ref(false); watch(information, () => { // 监听information ref的变化 const element = information.value; if (element) { const computedStyle = window.getComputedStyle(element); const lineClampValue = computedStyle.getPropertyValue('-webkit-line-clamp'); const textLineCount = [我需要计算文本行数] isTextTruncated.value = textLineCount > Number(lineClampValue); } });
解决方案
不需要计算具体行数,通过比较元素的scrollHeight和clientHeight即可判断文本是否被截断(超过3行)。以下是修正后的完整实现:
修正后的脚本
import { ref, watch, computed, nextTick, onMounted, onUnmounted } from 'vue'; const isExpanded = ref(true); // 默认处于截断状态 const information = ref(null); const isTextTruncated = ref(false); // 动态切换展开/收起按钮文字 const toggleCtaLabel = computed(() => isExpanded ? '展开' : '收起'); // 检查文本是否超过3行的核心函数 const checkTextTruncated = () => { const element = information.value; if (!element) return; // 保存当前元素的截断类状态 const hadTruncate = element.classList.contains('truncate'); // 临时添加截断类,确保测量的是截断状态下的高度 if (!hadTruncate) { element.classList.add('truncate'); } // 核心判断:scrollHeight > clientHeight 表示内容被截断(超过3行) isTextTruncated.value = element.scrollHeight > element.clientHeight; // 恢复元素原来的类状态 if (!hadTruncate) { element.classList.remove('truncate'); } }; // 监听文本内容变化,DOM更新后重新检查 watch(() => data?.information, () => { nextTick(checkTextTruncated); }); // 初始渲染和窗口尺寸变化时检查 onMounted(() => { checkTextTruncated(); window.addEventListener('resize', checkTextTruncated); }); onUnmounted(() => { window.removeEventListener('resize', checkTextTruncated); });
关键说明
- 高度比较逻辑:当元素应用
truncate类时,若scrollHeight(内容总高度)大于clientHeight(元素可见高度),则说明文本超过3行被截断。 - 全屏幕适配:添加窗口
resize事件监听,确保屏幕尺寸变化时能重新判断行数。 - DOM更新时机:用
nextTick确保文本内容更新后DOM已渲染完成,避免获取旧高度值。 - 状态不干扰:临时添加截断类测量后恢复原状态,不影响当前展开/收起的显示效果。
内容的提问来源于stack exchange,提问作者Pianoc
相关产品推荐
相关产品推荐

