You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计算文本行数,控制-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);
});

关键说明

  1. 高度比较逻辑:当元素应用truncate类时,若scrollHeight(内容总高度)大于clientHeight(元素可见高度),则说明文本超过3行被截断。
  2. 全屏幕适配:添加窗口resize事件监听,确保屏幕尺寸变化时能重新判断行数。
  3. DOM更新时机:用nextTick确保文本内容更新后DOM已渲染完成,避免获取旧高度值。
  4. 状态不干扰:临时添加截断类测量后恢复原状态,不影响当前展开/收起的显示效果。

内容的提问来源于stack exchange,提问作者Pianoc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 09:25:56