Vue3文本省略(Ellipsis)

71 篇文章 4 订阅
69 篇文章 3 订阅

效果如下图:在线预览

在这里插入图片描述

APIs

Ellipsis

参数说明类型默认值必传
maxWidth文本最大宽度number | string‘100%’false
line最大行数numberundefinedfalse
expand是否启用点击文本展开全部booleanfalsefalse
tooltip是否启用文本提示框booleantruefalse
tooltipPropstooltip 组件属性配置,参考 Tooltip Propsobject{}false

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?: number | string // 文本最大宽度
  line?: number // 最大行数
  expand?: boolean // 是否启用点击文本展开全部
  tooltip?: boolean // 是否启用文本提示框
  tooltipProps?: object // tooltip 组件属性配置
}
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"
    :overlayStyle="{ 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', { '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', { '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;
}
.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="{
        fontSize: 16,
        backgroundColor: '#4096ff',
        overlayStyle: { padding: '12px 16px', borderRadius: '12px' }
      }"
    >
      住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪
    </Ellipsis>
  </div>
</template>
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值