【vue2】文本自动省略组件,支持单行和多行省略,超出显示tooltip

代码见文末

vue3实现

最开始就用的vue3实现,如下

Vue3实现方式

vue2开发和使用文档

组件功能

TooltipText 是一个文字展示组件,具有以下功能:

  • 文本显示:支持单行和多行文本显示。
  • 自动判断溢出:判断文本是否溢出,根据溢出情况显示 tooltip。
  • 自定义样式:可以通过 props 修改文本样式和 Tooltip 样式。
  • 行数限制:支持多行文本显示,超出部分通过行数限制显示省略号。

使用方法
  1. 引入组件TooltipText 注册到你的 Vue 项目中:

    import TooltipText from './TooltipText.vue';
    
    export default {
      components: {
        TooltipText,
      },
    };
    
  2. 组件模板示例

    <template>
      <TooltipText
        :content="'这是一个演示文本。'"
        :lineClamp="2"
        :maxWidth="300"
        :tooltipOptions="{
          placement: 'top',
          effect: 'light',
          trigger: 'hover',
        }"
        :outStyle="{ color: '#333', fontSize: '16px' }"
      />
    </template>
    
  3. 传入参数

    属性名类型默认值说明
    tooltipOptionsObject{ content: 'Bottom center', placement: 'bottom', effect: 'dark', trigger: 'hover' }Tooltip 的配置选项,参考 Element UI 的配置。
    outStyleObject{ fontSize: '14px' }外部样式对象,用于自定义文字样式。
    contentString''显示的文本内容。
    lineClampNumber1显示的行数限制,超出部分会显示省略号。
    maxWidthNumber0Tooltip 的最大宽度(单位 px)。
  4. 样式自定义 可通过 tooltipOptionsoutStyle 自定义 Tooltip 和文字样式:

    :tooltipOptions="{
      effect: 'light',
      placement: 'right',
      trigger: 'hover',
    }"
    :outStyle="{ fontSize: '18px', color: '#555' }"
    
  5. 动态内容 内容变动后会自动检查溢出并更新 Tooltip 显示状态,无需额外操作。


开发细节
  1. 溢出检查

    • 单行文本通过 scrollWidthclientWidth 比较实现。
    • 多行文本通过 scrollHeightclientHeight 比较实现。
  2. 计算属性

    • computedMaxPopWidth 动态计算 Tooltip 的最大宽度,默认为文字容器宽度的 50%。
    • computedIfWrap 判断是否为多行文本,根据 lineClamp 属性动态更新。
  3. 监听与更新

    • 使用 watch 监听 content 的变动,在内容更新后重新计算溢出状态。
  4. 样式

    • text-auto-nowrap:单行文本样式,自动截断显示省略号。
    • text-auto-wrap:多行文本样式,支持行数限制。

注意事项
  • 如果文本内容较长但设置了过小的 maxWidth,可能导致 Tooltip 内容显示不全。
  • 若需要动态调整文本或 Tooltip 样式,请确保 props 数据及时更新。

通过此组件可以轻松实现文本展示与溢出提示的功能,并满足多样化的样式需求。

<template>
  <!-- Tooltip and text display container -->
  <div>
    <!-- Tooltip element from Element UI -->
    <el-tooltip
      v-bind="tooltipOptions" <!-- Bind tooltip options -->
      :popper-class="!toolTipShow ? 'hide-tooltip tooltip-popper' : 'tooltip-popper'" <!-- Conditionally apply tooltip classes -->
    >
      <!-- Tooltip content slot -->
      <template #content>
        <div 
          class="tooltip-content" 
          :style="{ maxWidth: maxWidth || computedMaxPopWidth + 'px' }" <!-- Set maximum width for tooltip content -->
        >
          {{ content }} <!-- Display tooltip content -->
        </div>
      </template>

      <!-- Text display with optional line clamp and styles -->
      <div
        :class="{ 'text-auto-wrap': computedIfWrap, 'text-auto-nowrap': !computedIfWrap }" <!-- Apply wrapping styles based on computed value -->
        ref="textAutoRef" <!-- Reference for DOM access -->
        :style="{
          '-webkit-line-clamp': lineClamp, <!-- Apply line clamp for text -->
          'line-clamp': lineClamp, <!-- Apply line clamp for text -->
          ...outStyle <!-- Merge additional styles -->
        }"
      >
        {{ content }} <!-- Display main text content -->
      </div>
    </el-tooltip>
  </div>
</template>

<script>
export default {
  name: 'TooltipText',

  props: {
    // Tooltip options passed to Element UI el-tooltip
    tooltipOptions: {
      type: Object,
      default: () => ({
        content: 'Bottom center',
        placement: 'bottom',
        effect: 'dark',
        trigger: 'hover',
      }),
    },
    // Additional styles for the text container
    outStyle: {
      type: Object,
      default: () => ({
        fontSize: '14px',
      }),
    },
    // Text content to display
    content: {
      type: String,
      default: '',
    },
    // Number of lines to clamp text to
    lineClamp: {
      type: Number,
      default: 1,
    },
    // Maximum width for tooltip content
    maxWidth: {
      type: Number,
      default: 0,
    },
  },

  data() {
    return {
      toolTipShow: false, // Whether to show the tooltip
      textAutoRef: null, // Reference to the text container element
    };
  },

  computed: {
    // Compute the maximum width for the tooltip dynamically
    computedMaxPopWidth() {
      if (this.$refs.textAutoRef) {
        return this.$refs.textAutoRef.clientWidth * 0.5; // Tooltip width is half of the text container width
      }
      return '100%'; // Default to full width if reference is not available
    },

    // Determine if text wrapping should be applied based on lineClamp
    computedIfWrap() {
      return this.lineClamp > 1;
    },
  },

  watch: {
    // Watch for changes in content and re-check overflow
    content: {
      handler() {
        this.$nextTick(() => {
          this.checkOverflow();
        });
      },
      immediate: true,
    },
  },

  methods: {
    // Check if the text content overflows its container
    checkOverflow() {
      if (!this.$refs.textAutoRef) return;

      if (!this.computedIfWrap) {
        // Single-line text overflow check
        this.toolTipShow = this.$refs.textAutoRef.scrollWidth > this.$refs.textAutoRef.clientWidth;
      } else {
        // Multi-line text overflow check
        this.toolTipShow = this.$refs.textAutoRef.scrollHeight > this.$refs.textAutoRef.clientHeight;
      }
    },
  },

  mounted() {
    // Perform overflow check after component is mounted
    this.$nextTick(this.checkOverflow);
  },
};
</script>

<style lang="scss" scoped>
  .text-auto-nowrap {
    width: 100%;
    white-space: nowrap; <!-- Prevent text wrapping -->
    overflow: hidden; <!-- Hide overflowing text -->
    text-overflow: ellipsis; <!-- Show ellipsis for overflow -->
    text-align: left; <!-- Align text to the left -->
  }

  .text-auto-wrap {
    width: 100%;
    text-align: left; <!-- Align text to the left -->
    overflow: hidden; <!-- Hide overflowing text -->
    text-overflow: ellipsis; <!-- Show ellipsis for overflow -->
    display: -webkit-box; <!-- Use a flex container for wrapping -->
    -webkit-box-orient: vertical; <!-- Set vertical orientation for line clamp -->
  }
</style>

<style>
  .hide-tooltip {
    visibility: hidden !important; <!-- Hide the tooltip completely -->
  }
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值