从零开始Vue3+Element Plus后台管理系统(26) 多行文字展开折叠

从零开始Vue3+Element Plus后台管理系统(26) 多行文字展开折叠

多行文字超出部门截断,并且可以展开收起。这个需求其实很容易实现,只需要 CSS 和一点简单的 JS 就可以。本文只讨论利用 css 截断,不考虑直接截取文字(不付费不给看剩余内容)的情况。

实现一个基础版本 1.0







  



















<div class="more-text">文字内容。。。</div>

先从简单的开始,html 把需要显示的文本放进来就好,然后交给 CSS 和 JS。

下面我们需要使用 css 变量,row 是可配置的(通过 props传递),height 为实际显示的高度,根据 row 计算得出。

需要先在 js 中给 css 变量 –row 和–height 赋值,然后在 style 中使用。

 refMoreText.value.style.setProperty('--row', props.row)
 refMoreText.value.style.setProperty('--height', textHeight + 'px')
.more-text {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  word-break: break-all;
  white-space: pre-wrap;
  -webkit-line-clampvar(--row);
  line-clampvar(--row);
  heightvar(--height);
从零开始Vue3+Element Plus后台管理系统(26) 多行文字展开折叠

至此,省略号效果实现了,然后加上 展开/收起效果,修改html 如下:

  1. 增加几个 ref 便于计算高度

  2. isExceed 表示是否超出高度,如果为 true,显示“展开更多”,反之不显示。

<div ref="refMoreText" class="more-text">
    <div ref="refContent" class="content">{{ text }}</div>
    <div
      ref="refTrigger"
      class="trigger text-primary trigger-bg"
      @click="handleTrigger"
      v-if="isExceed"
    >

      <span>{{ moreVisible ? '收起' : '... 展开更多' }}</span>
    </div>
  </div>
...
    // 实际内容的高度
    fullHeight = refContent.value.clientHeight
    // 文本的行高,用于计算 n 行所占的高度
    lineHeight = Number(window.getComputedStyle(refMoreText.value).lineHeight.slice(0-2))
    // n 行的高度
    textHeight = lineHeight * props.row
    // 判断是否超出高度
    isExceed.value = textHeight < fullHeight
...

这里 css 有一个小技巧,我们把content的 position 设为 absolute,这样它不会被父元素的高度影响,方便获取完整文本的实际高度。

从零开始Vue3+Element Plus后台管理系统(26) 多行文字展开折叠
image.png
 .content {
    // 设为absolute,避免高度被父元素影响
    position: absolute;
    height: auto;
  }

获取完整文本的高度,还有一个重要作用:

当我们使用 transition 来实现展开折叠的动画效果,需要有开始高度和结束高度,如果结束高度 height设为 auto,那么这个过度动画就不会生小,展开效果比较生硬。

另一个 css 小技巧:我们给“展开更多”加了一点渐变背景,让它和文字看起来更协调。

从零开始Vue3+Element Plus后台管理系统(26) 多行文字展开折叠
image.png
 .trigger-bg {
    backgroundlinear-gradient(
      to right,
      rgb(25525525500,
      rgb(255255255160%,
      #fff 100%
    );
  }

接下来,我们通过展开/折叠状态,在 js 中设置对应的 css 变量

// visible 
// true:展开,false:折叠
const setCssVar = (visible: boolean) => {
  if (visible) {
    refMoreText.value.style.setProperty('--height', fullHeight + lineHeight + 'px')
    refMoreText.value.style.setProperty('--row''')
  } else {
    refMoreText.value.style.setProperty('--row', props.row)
    // 收起在文本下面,所以额外增加一行的高度
    refMoreText.value.style.setProperty('--height', textHeight + 'px')
  }
}

至此,已经实现了 1.0 版本,不过有一点小问题:在改变窗口或者容器大小时,展开内容的高度不会变,收起按钮的位置也不会跟着变化。

我希望它具有更好的自适应能力,继续完善 1.1 版本。

增强自适应能力

通过监听内容区域的变化,实时改变元素的高度。这里使用 Resize Observer API(文档参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Resize_Observer_API),相对window resize 事件,Resize Observer的性能更优。

let resizeObserver: ResizeObserver | null = null

onMounted(async () => {
  fullHeight = refContent.value.clientHeight

  lineHeight = Number(window.getComputedStyle(refMoreText.value).lineHeight.slice(0-2))

  textHeight = lineHeight * props.row

  if (refTrigger.value) refTrigger.value.style['lineHeight'] = lineHeight + 'px'

  resizeObserver = new ResizeObserver((entries) => {
    for (let entry of entries) {
      fullHeight = entry.contentRect.height
      isExceed.value = textHeight < fullHeight
      setCssVar(moreVisible.value)
    }
  })
  resizeObserver.observe(refContent.value)
})

const unobserveElementSize = () => {
  if (resizeObserver) {
    resizeObserver.disconnect()
    resizeObserver = null
  }
}


onUnmounted(() => {
  unobserveElementSize()
})

OK,已经实现了我需要的一个 MoMoreText 组件。

如果你有什么好的想法和建议,可以给我留言

项目地址

本项目GIT地址:https://github.com/lucidity99/mocha-vue3-system

如果有帮助,给个star ✨ 点个赞

原文始发于微信公众号(自由前端之路):从零开始Vue3+Element Plus后台管理系统(26) 多行文字展开折叠

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/292000.html

(0)
李, 若俞的头像李, 若俞

相关推荐

发表回复

登录后才能评论
极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!