Vue3文本省略(Ellipsis)

简介: 这是一个基于Vue3的文本省略组件(Ellipsis),支持单行或多行文本的自动省略与展开功能,并可自定义提示框(Tooltip)的内容与样式。

效果如下图:在线预览

在这里插入图片描述

APIs

Ellipsis

参数 说明 类型 默认值
maxWidth 文本最大宽度,单位 px number | string ‘100%’
line 最大行数 number undefined
expand 是否启用点击文本展开全部 boolean false
tooltip 是否启用文本提示框 boolean true
tooltipProps Tooltip 组件属性配置,参考 Tooltip Props object {}

Events

名称 说明 类型
expandChange 点击文本展开收起时的回调 (expand: boolean) => void

创建文本省略组件Ellipsis.vue

其中引入使用了以下组件和工具函数:

<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import Tooltip from '../tooltip'
import { useResizeObserver } from '../utils'
interface Props {
  maxWidth?: string | number // 文本最大宽度,单位 px
  line?: number // 最大行数
  expand?: boolean // 是否启用点击文本展开全部
  tooltip?: boolean // 是否启用文本提示框
  tooltipProps?: object // Tooltip 组件属性配置,参考 Tooltip Props
}
const props = withDefaults(defineProps<Props>(), {
  maxWidth: '100%',
  line: undefined,
  expand: false,
  tooltip: true,
  tooltipProps: () => ({})
})
const showTooltip = ref(false) // 是否显示提示框
const showExpand = ref(false) // 是否可以启用点击展开
const ellipsisRef = ref()
const defaultTooltipMaxWidth = ref()
const textMaxWidth = computed(() => {
  if (typeof props.maxWidth === 'number') {
    return props.maxWidth + 'px'
  }
  return props.maxWidth
})
watch(
  () => [props.maxWidth, props.line, props.tooltip],
  () => {
    if (props.tooltip) {
      showTooltip.value = getTooltipShow()
    }
  },
  {
    deep: true,
    flush: 'post'
  }
)
useResizeObserver(ellipsisRef, () => {
  if (props.tooltip) {
    showTooltip.value = getTooltipShow()
  }
})
onMounted(() => {
  if (props.tooltip) {
    showTooltip.value = getTooltipShow()
  }
})
function getTooltipShow() {
  const scrollWidth = ellipsisRef.value.scrollWidth
  const scrollHeight = ellipsisRef.value.scrollHeight
  const clientWidth = ellipsisRef.value.clientWidth
  const clientHeight = ellipsisRef.value.clientHeight
  if (scrollWidth > clientWidth || scrollHeight > clientHeight) {
    defaultTooltipMaxWidth.value = ellipsisRef.value.offsetWidth + 24
    if (props.expand) {
      showExpand.value = true
    }
    return true
  } else {
    if (props.expand) {
      showExpand.value = false
    }
    return false
  }
}
const emit = defineEmits(['expandChange'])
function onExpand() {
  if (ellipsisRef.value.style['-webkit-line-clamp']) {
    if (props.tooltip) {
      showTooltip.value = false
      nextTick(() => {
        ellipsisRef.value.style['-webkit-line-clamp'] = ''
      })
    } else {
      ellipsisRef.value.style['-webkit-line-clamp'] = ''
    }
    emit('expandChange', true)
  } else {
    if (props.tooltip) {
      showTooltip.value = true
    }
    ellipsisRef.value.style['-webkit-line-clamp'] = props.line
    emit('expandChange', false)
  }
}
</script>
<template>
  <Tooltip
    v-if="showTooltip"
    :max-width="defaultTooltipMaxWidth"
    :tooltip-style="{ padding: '8px 12px', textAlign: 'justify' }"
    v-bind="tooltipProps"
  >
    <template #tooltip>
      <slot name="tooltip">
        <slot></slot>
      </slot>
    </template>
    <div
      ref="ellipsisRef"
      class="m-ellipsis"
      :class="[line ? 'ellipsis-line' : 'not-ellipsis-line', { 'ellipsis-cursor-pointer': showExpand }]"
      :style="`-webkit-line-clamp: ${line}; max-width: ${textMaxWidth};`"
      @click="showExpand ? onExpand() : () => false"
      v-bind="$attrs"
    >
      <slot></slot>
    </div>
  </Tooltip>
  <div
    v-else
    ref="ellipsisRef"
    class="m-ellipsis"
    :class="[line ? 'ellipsis-line' : 'not-ellipsis-line', { 'ellipsis-cursor-pointer': showExpand }]"
    :style="`-webkit-line-clamp: ${line}; max-width: ${textMaxWidth};`"
    @click="showExpand ? onExpand() : () => false"
    v-bind="$attrs"
  >
    <slot></slot>
  </div>
</template>
<style lang="less" scoped>
.m-ellipsis {
  overflow: hidden;
  cursor: text;
}
.ellipsis-line {
  display: -webkit-inline-box;
  -webkit-box-orient: vertical;
}
.not-ellipsis-line {
  display: inline-block;
  vertical-align: bottom;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.ellipsis-cursor-pointer {
  cursor: pointer;
}
</style>

在要使用的页面引入

<script setup lang="ts">
import Ellipsis from './Ellipsis.vue'
</script>
<template>
  <div>
    <h1>{
  { $route.name }} {
  { $route.meta.title }}</h1>
    <h2 class="mt30 mb10">基本使用</h2>
    <Ellipsis :maxWidth="240">住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪</Ellipsis>
    <h2 class="mt30 mb10">多行省略</h2>
    <Ellipsis :line="2">
      电灯熄灭 物换星移 泥牛入海
      <br />
      黑暗好像 一颗巨石 按在胸口
      <br />
      独脚大盗 百万富翁 摸爬滚打
      <br />
      黑暗好像 一颗巨石 按在胸口
    </Ellipsis>
    <h2 class="mt30 mb10">点击展开</h2>
    <Ellipsis expand :line="2">
      电灯熄灭 物换星移 泥牛入海
      <br />
      黑暗好像 一颗巨石 按在胸口
      <br />
      独脚大盗 百万富翁 摸爬滚打
      <br />
      黑暗好像 一颗巨石 按在胸口
    </Ellipsis>
    <h2 class="mt30 mb10">定制 Tooltip 内容</h2>
    <Ellipsis :max-width="240">
      住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪
      <template #tooltip>
        <div style="text-align: center">
          《秦皇岛》
          <br />
          住在我心里孤独的
          <br />
          孤独的海怪 痛苦之王
          <br />
          开始厌倦 深海的光 停滞的海浪
        </div>
      </template>
    </Ellipsis>
    <h2 class="mt30 mb10">自定义 Tooltip 样式</h2>
    <Ellipsis
      :max-width="240"
      :tooltip-props="{
        bgColor: '#4096ff',
        tooltipStyle: {
          padding: '12px 16px',
          borderRadius: '12px',
          fontSize: '16px',
          backgroundColor: '#4096ff'
        }
      }"
    >
      住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪
    </Ellipsis>
  </div>
</template>
相关文章
|
6月前
|
JavaScript 前端开发 安全
Vue 3
Vue 3以组合式API、Proxy响应式系统和全面TypeScript支持,重构前端开发范式。性能优化与生态协同并进,兼顾易用性与工程化,引领Web开发迈向高效、可维护的新纪元。(238字)
888 139
|
11月前
|
缓存 JavaScript PHP
斩获开发者口碑!SnowAdmin:基于 Vue3 的高颜值后台管理系统,3 步极速上手!
SnowAdmin 是一款基于 Vue3/TypeScript/Arco Design 的开源后台管理框架,以“清新优雅、开箱即用”为核心设计理念。提供角色权限精细化管理、多主题与暗黑模式切换、动态路由与页面缓存等功能,支持代码规范自动化校验及丰富组件库。通过模块化设计与前沿技术栈(Vite5/Pinia),显著提升开发效率,适合团队协作与长期维护。项目地址:[GitHub](https://github.com/WANG-Fan0912/SnowAdmin)。
1256 5
|
6月前
|
缓存 JavaScript 算法
Vue 3性能优化
Vue 3 通过 Proxy 和编译优化提升性能,但仍需遵循最佳实践。合理使用 v-if、key、computed,避免深度监听,利用懒加载与虚拟列表,结合打包优化,方可充分发挥其性能优势。(239字)
486 1
|
7月前
|
开发工具 iOS开发 MacOS
基于Vite7.1+Vue3+Pinia3+ArcoDesign网页版webos后台模板
最新版研发vite7+vue3.5+pinia3+arco-design仿macos/windows风格网页版OS系统Vite-Vue3-WebOS。
767 11
|
6月前
|
JavaScript 安全
vue3使用ts传参教程
Vue 3结合TypeScript实现组件传参,提升类型安全与开发效率。涵盖Props、Emits、v-model双向绑定及useAttrs透传属性,建议明确声明类型,保障代码质量。
546 0
|
8月前
|
缓存 前端开发 大数据
虚拟列表在Vue3中的具体应用场景有哪些?
虚拟列表在 Vue3 中通过仅渲染可视区域内容,显著提升大数据列表性能,适用于 ERP 表格、聊天界面、社交媒体、阅读器、日历及树形结构等场景,结合 `vue-virtual-scroller` 等工具可实现高效滚动与交互体验。
833 1
|
8月前
|
缓存 JavaScript UED
除了循环引用,Vue3还有哪些常见的性能优化技巧?
除了循环引用,Vue3还有哪些常见的性能优化技巧?
444 0
|
9月前
|
JavaScript
vue3循环引用自已实现
当渲染大量数据列表时,使用虚拟列表只渲染可视区域的内容,显著减少 DOM 节点数量。
205 0
|
11月前
|
JavaScript API 容器
Vue 3 中的 nextTick 使用详解与实战案例
Vue 3 中的 nextTick 使用详解与实战案例 在 Vue 3 的日常开发中,我们经常需要在数据变化后等待 DOM 更新完成再执行某些操作。此时,nextTick 就成了一个不可或缺的工具。本文将介绍 nextTick 的基本用法,并通过三个实战案例,展示它在表单验证、弹窗动画、自动聚焦等场景中的实际应用。
1057 17
|
11月前
|
JavaScript 前端开发 API
Vue 2 与 Vue 3 的区别:深度对比与迁移指南
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架,在过去的几年里,Vue 2 一直是前端开发中的重要工具。而 Vue 3 作为其升级版本,带来了许多显著的改进和新特性。在本文中,我们将深入比较 Vue 2 和 Vue 3 的主要区别,帮助开发者更好地理解这两个版本之间的变化,并提供迁移建议。 1. Vue 3 的新特性概述 Vue 3 引入了许多新特性,使得开发体验更加流畅、灵活。以下是 Vue 3 的一些关键改进: 1.1 Composition API Composition API 是 Vue 3 的核心新特性之一。它改变了 Vue 组件的代码结构,使得逻辑组
2243 0

热门文章

最新文章