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

Vue中如何仅为被截断文本的span显示title属性?

问题

我有一个动态生成的表格,为td内的span添加了truncate类来缩短长文本,同时设置title以显示完整内容。但现在所有span都显示title,我只想让被截断的span显示title,该如何实现?

解决方案

核心逻辑是判断文本是否真的被截断:当元素的scrollWidth(内容实际宽度)大于clientWidth(元素可见宽度)时,说明文本被截断,此时才设置title属性,否则清空title。

方法一:自定义Vue指令(推荐,可复用)

通过自定义指令封装判断逻辑,自动处理元素的截断状态:

Vue.directive('truncate-title', {
  bind(el) {
    updateTitle(el);
  },
  update(el) {
    // 数据更新后等待DOM渲染完成再重新判断
    Vue.nextTick(() => updateTitle(el));
  }
});

// 统一处理title的逻辑函数
function updateTitle(el) {
  const isTruncated = el.scrollWidth > el.clientWidth;
  el.title = isTruncated ? el.textContent : '';
}

Vue.component('TheTable', {
  template: `<table class="table">
    <tr v-for="(row, i) in data">
      <td v-for="(item, index) in row">
        <span class="truncate" v-truncate-title>
          {{ item }}
        </span>
      </td>
    </tr>
  </table>`,
  data() {
    return {
      data: [
        [
          'very very very very very very very very very very very very very very big sentence',
          'very very very very very very very very very very very very very very big sentence',
          'very very very very very very very very very very very very very very big sentence'
        ],
        ['aaa', 'bbb', 'ccc'],
        ['ddd', 'eee', 'fff']
      ]
    }
  }
})

new Vue({
  el: "#app",
});

方法二:组件内钩子处理

如果不想用自定义指令,也可以在组件的生命周期钩子中遍历元素处理:

Vue.component('TheTable', {
  template: `<table class="table">
    <tr v-for="(row, i) in data">
      <td v-for="(item, index) in row">
        <span class="truncate" ref="truncateSpans">
          {{ item }}
        </span>
      </td>
    </tr>
  </table>`,
  data() {
    return {
      data: [
        [
          'very very very very very very very very very very very very very very big sentence',
          'very very very very very very very very very very very very very very big sentence',
          'very very very very very very very very very very very very very very big sentence'
        ],
        ['aaa', 'bbb', 'ccc'],
        ['ddd', 'eee', 'fff']
      ]
    }
  },
  mounted() {
    this.updateTitles();
  },
  updated() {
    Vue.nextTick(() => this.updateTitles());
  },
  methods: {
    updateTitles() {
      this.$refs.truncateSpans.forEach(span => {
        span.title = span.scrollWidth > span.clientWidth ? span.textContent : '';
      });
    }
  }
})

new Vue({
  el: "#app",
});

原有CSS和HTML部分(无需修改)

.truncate {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.table td {
  max-width: 100px;
}
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap@4.5.3/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.css" />

<script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.min.js"></script>

<div id="app">
  <the-table/>
</div>

关键说明

  • scrollWidth:元素内容的实际宽度(包含被隐藏的部分)
  • clientWidth:元素的可见宽度
  • Vue.nextTick():确保DOM更新完成后再执行判断,避免数据更新后DOM未渲染导致判断错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:42:28