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

发布于:2024-12-18 ⋅ 阅读:(161) ⋅ 点赞:(0)

代码见文末

vue2实现

最近开发也用到了vue2,随即使用魔法优化改写了一下

v​​​​​​​​​​​​​​vue2实现方式

vue3开发与使用文档:可自适应显示内容的 Tooltip 组件


组件介绍

该组件基于 Vue 3 和 Element Plus 构建,主要功能是通过 el-tooltip 实现内容的动态展示。若文本内容超出容器范围,则自动显示 Tooltip 提示框,同时支持自定义行数的裁剪(line-clamp)。


开发背景

在前端开发中,长文本内容需要在有限空间中展示时,为了避免视觉杂乱,通常使用文字裁剪和 Tooltip 的组合方案。此组件适合展示动态内容或受限空间的文本场景。


使用指南

组件 Props
参数 类型 默认值 必填 说明
toolTipOptions Object {placement: 'bottom', effect: 'dark', trigger: 'hover'} Tooltip 配置项,支持所有 el-tooltip 的属性。
outStyle Object { fontSize: '14px' } 外层容器样式,支持传入自定义样式。
content String 要显示的内容。
lineClamp Number 1 显示行数,当超过行数时自动裁剪并显示 Tooltip。
maxWidth Number 0 Tooltip 的最大宽度(单位:px)。若为 0,则按当前文字容器宽度的 50% 设置。

示例代码
基础使用
<template>
  <AdaptiveTooltip 
    :content="'这是一个很长的文本内容,当超出容器范围时会显示 Tooltip 提示框。'" 
    :lineClamp="2"
  />
</template>

<script setup>
import AdaptiveTooltip from './AdaptiveTooltip.vue';
</script>

自定义 Tooltip 配置
<template>
  <AdaptiveTooltip 
    :toolTipOptions="{ placement: 'top', effect: 'light', trigger: 'click' }" 
    :content="'点击显示的 Tooltip 文本内容。'"
    :lineClamp="1"
  />
</template>

限制 Tooltip 最大宽度
<template>
  <AdaptiveTooltip 
    :content="'这是一个长文本,当文本超出容器范围时会显示 Tooltip,同时 Tooltip 宽度不超过 300px。'" 
    :lineClamp="1"
    :maxWidth="300"
  />
</template>

自定义外部样式
<template>
  <AdaptiveTooltip 
    :content="'自定义字体样式的文本内容。'" 
    :outStyle="{ color: '#f56c6c', fontWeight: 'bold' }" 
    :lineClamp="1"
  />
</template>

组件样式
  1. 文本裁剪样式
    组件支持两种文本裁剪模式:

    • 单行文本裁剪(text-auto-nowrap):通过 white-space: nowrap 实现单行裁剪。
    • 多行文本裁剪(text-auto-wrap):通过 CSS 属性 -webkit-line-clamp 实现多行裁剪。
  2. Tooltip 样式
    默认情况下,Tooltip 的宽度是文字容器宽度的 50%。开发者可通过 maxWidth 修改。


开发注意事项
  1. 组件依赖

    • Vue 3
    • Element Plus
    • TypeScript (可选)
  2. 动态宽度计算
    Tooltip 宽度动态计算基于文字容器宽度,因此在 onMounted 时绑定了 DOM 引用。

  3. 行数校验
    使用 lineClamp 时,校验其值为大于 0 的整数。

  4. 自适应溢出显示
    根据 scrollWidthclientWidth 判断文本是否超出容器范围。


代码

        

<template>
  <div>
    <el-tooltip
      v-bind="props.toolTipOptions"
      :popper-class="['tooltip-popper', { 'hide-tooltip': !toolTipShow }]"
    >
      <template #content>
        <div class="tooltip-content" :style="{ maxWidth: contentMaxWidth }">
          {{ props.content }}
        </div>
      </template>
      <div
        :class="{ 'text-auto-wrap': ifWrap, 'text-auto-nowrap': !ifWrap }"
        ref="textAutoRef"
        :style="{
          '-webkit-line-clamp': props.lineClamp,
          'line-clamp': props.lineClamp,
          ...props.outStyle
        }"
      >
        {{ props.content }}
      </div>
    </el-tooltip>
  </div>
</template>

<script setup lang="ts">
import { onMounted, defineProps, ref, computed } from 'vue';

interface ToolTipOptions {
  content?: string;
  placement?: 'top' | 'bottom' | 'left' | 'right';
  effect?: 'dark' | 'light';
  trigger?: 'hover' | 'click' | 'focus';
  [key: string]: any;
}

const props = defineProps({
  toolTipOptions: {
    type: Object as () => ToolTipOptions,
    default: () => ({
      placement: 'bottom',
      effect: 'dark',
      trigger: 'hover',
    }),
  },
  outStyle: {
    type: Object,
    default: () => ({
      fontSize: '14px',
    }),
  },
  content: {
    type: String,
    default: '',
    required: true,
  },
  lineClamp: {
    type: Number,
    default: 1,
    validator: (value: number) => value > 0,
  },
  maxWidth: {
    type: Number,
    default: 0,
  },
});

const POPUP_WIDTH_RATIO = 0.5; // 弹出框宽度比例
const textAutoRef = ref<HTMLElement | null>(null);
const toolTipShow = ref(false);

const maxPopWidth = computed(() => {
  if (textAutoRef.value) {
    return textAutoRef.value.clientWidth * POPUP_WIDTH_RATIO;
  }
  return 0;
});

const contentMaxWidth = computed(() => {
  if (props.maxWidth) return `${props.maxWidth}px`;
  return `${maxPopWidth.value}px`;
});

const ifWrap = computed(() => {
  return props.lineClamp > 1;
});

onMounted(() => {
  if (!textAutoRef.value) return;

  const isOverflow = !ifWrap.value
    ? textAutoRef.value.scrollWidth > textAutoRef.value.clientWidth
    : textAutoRef.value.scrollHeight > textAutoRef.value.clientHeight;

  toolTipShow.value = isOverflow;
});
</script>

<style lang="less" scoped>
.text-auto-nowrap {
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: left;
}

.text-auto-wrap {
  width: 100%;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
}

:deep(.tooltip-popper) {
  max-width: 50%;
}

:deep(.hide-tooltip) {
  visibility: hidden !important;
}
</style>


网站公告

今日签到

点亮在社区的每一天
去签到