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

Vuetify 3数据表格长文本View More功能实现问题求助

Vuetify 3 数据表格实现「View More/View Less」按钮方案

针对你遇到的两个问题,以下是完整的修复实现:

核心问题分析

  1. ref 管理错误:原代码中单个descriptionRef无法区分表格中每一行的描述元素,需要用对象存储每个行对应的 DOM 引用。
  2. DOM 时机问题:mounted钩子执行时表格可能还未完全渲染,需要等待 DOM 更新完成后再判断文本截断状态。
  3. 截断判断逻辑缺失:未实现scrollHeight与clientHeight的比较逻辑。

完整实现代码

<template>
  <v-data-table :headers="headers" :items="items">
    <template #item.description="{ item }">
      <div class="description-wrapper">
        <div
          :ref="el => descriptionRefs[item.name] = el"
          class="three_lines_description"
          :class="{ expanded: isExpanded[item.name] }"
        >
          {{ item.description }}
        </div>
        <v-btn
          v-if="isTruncated[item.name]"
          @click="toggleExpand(item.name)"
          text
          size="small"
        >
          {{ isExpanded[item.name] ? 'View Less' : 'View More' }}
        </v-btn>
      </div>
    </template>
  </v-data-table>
</template>

<script>
import { nextTick, onMounted, onUnmounted, reactive } from 'vue';

export default {
  setup() {
    const headers = [
      { title: "Name", key: "name" },
      { title: "Email", key: "email" },
      { title: "Description", key: "description" },
    ];

    const items = reactive([
      {
        name: "Alice",
        email: "alice@example.com",
        description: "短描述"
      },
      {
        name: "Bob",
        email: "bob@example.com",
        description: "这是一段超过三行的测试描述文本,用来验证View More按钮的显示逻辑。这是一段超过三行的测试描述文本,用来验证View More按钮的显示逻辑。这是一段超过三行的测试描述文本,用来验证View More按钮的显示逻辑。"
      },
      {
        name: "Charlie",
        email: "charlie@example.com",
        description: "中等长度描述文本,刚好两行左右,不会触发View More按钮。中等长度描述文本,刚好两行左右。"
      }
    ]);

    const isExpanded = reactive({});
    const isTruncated = reactive({});
    const descriptionRefs = reactive({});

    const toggleExpand = (name) => {
      isExpanded[name] = !isExpanded[name];
    };

    const checkTruncation = () => {
      Object.keys(descriptionRefs).forEach(name => {
        const el = descriptionRefs[name];
        if (!el) return;
        // 重置展开状态,确保判断基于截断状态的高度
        isExpanded[name] = false;
        // 等待DOM更新后再获取正确的高度
        nextTick(() => {
          isTruncated[name] = el.scrollHeight > el.clientHeight;
        });
      });
    };

    onMounted(() => {
      // 等待表格DOM完全渲染后执行判断
      nextTick(checkTruncation);
      // 监听窗口大小变化,重新判断截断状态
      window.addEventListener('resize', checkTruncation);
    });

    onUnmounted(() => {
      window.removeEventListener('resize', checkTruncation);
    });

    return {
      headers,
      items,
      isExpanded,
      isTruncated,
      toggleExpand
    };
  }
};
</script>

<style scoped>
.three_lines_description {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  transition: max-height 0.3s ease;
  max-height: calc(1.5em * 3); /* 假设行高为1.5em,可根据实际调整 */
}

.three_lines_description.expanded {
  -webkit-line-clamp: unset;
  max-height: none;
  overflow: visible;
}

.description-wrapper {
  margin: 0.5em 0;
}
</style>

关键修改说明

  • Ref 管理:使用descriptionRefs对象存储每个行的 DOM 引用,通过:ref="el => descriptionRefs[item.name] = el"绑定每个描述元素。
  • DOM 时机处理:在onMounted中通过nextTick确保表格渲染完成后再执行截断判断,同时监听窗口 resize 事件,适配屏幕变化。
  • 样式优化:添加expanded类控制展开/收起状态,使用max-height配合过渡动画提升体验,明确设置三行的最大高度确保判断准确。
  • 截断判断逻辑:通过比较scrollHeight(文本完整高度)和clientHeight(容器显示高度),确定文本是否被截断,设置isTruncated状态控制按钮显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:49:50