记录--多行标签超出展开折叠功能

这篇具有很好参考价值的文章主要介绍了记录--多行标签超出展开折叠功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

记录--多行标签超出展开折叠功能

前言

 记录分享每一个日常开发项目中的实用小知识,不整那些虚头巴脑的框架理论与原理,之前分享过抽奖功能、签字功能等,有兴趣的可以看看本人以前的分享。  今天要分享的实用小知识是最近项目中遇到的标签相关的功能,我不知道叫啥,姑且称之为【多行标签展开隐藏】功能吧,类似于多行文本展开折叠功能,如果超过最大行数则显示展开隐藏按钮,如果不超过则不显示按钮。多行文本展开与折叠功能在网上有相当多的文章了,也有许多开源的封装组件,而多行标签展开隐藏的文章却比较少,刚好最近我也遇到了这个功能,所以就单独拿出来与大家分享如何实现。

出处

 【多行标签展开与隐藏】该功能我们平时可能没注意一般在哪里会有,其实最常见的就是各种APP的搜索页面的历史记录这里,下面是我从拼多多(左)和腾讯学堂小程序(右)截下来的功能样式:

记录--多行标签超出展开折叠功能

其它APP一般搜索的历史记录这里都有这个小功能,比如京东、支付宝、淘宝、抖音、快手等,可能稍有点儿不一样,有的是按钮样式,有的是只有展开没有收起功能,可能我们用过了很多年平时都没有注意到这个小功能,有想了解的可以去看一看哈。如果有一天你们需要开发一个搜索页面的话产品就很有可能出这样的一个功能,接下来我们就来看看这种功能我们该如何实现。

功能实现

我们先看实现的效果图,然后再分析如何实现,效果图如下:

记录--多行标签超出展开折叠功能

【样式一】:标签容器和展开隐藏按钮分开(效果图样式一)

 标签容器和按钮分开的这种样式功能实现起来的话我个人觉得难度稍微简单一些,下面我们看看如何实现这种分开的功能。

第一种方法:通过与第一个标签左偏移值对比实现

原理:遍历每个标签然后通过与第一个标签左偏移值对比,如果有几个相同偏移值则说明有几个换行

具体实现上代码:

<div class="list-con list-con-1">
  <div class="label">人工智能</div>
  <div class="label">人工智能与应用</div>
  <div class="label">行业分析与市场数据</div>
  <div class="label">标签标签标签标签标签标签标签标签</div>
  <div class="label">标签</div>
  <div class="label">啊啊啊</div>
  <div class="label">宝宝贝贝</div>
  <div class="label">微信</div>
  <div class="label">吧啊啊</div>
  <div class="label">哦哦哦哦哦哦哦哦</div>
</div>
<div class="expand expand-1">展开 ∨</div>



<script>
  const listCon = document.querySelector('.list-con-1')
  const expandBtn = document.querySelector('.expand-1')
  console.log(listCon.children)
  // HTMLCollection对象 item()、namedItem()方法 length属性
  let firstLabelOffsetLeft = 0 // 第一个标签左侧偏移
  let line = 1 // 记录行
  const len = listCon.children.length
  for(let i = 0; i < len; i++) {
    const _offsetLeft = listCon.children.item(i).offsetLeft
    if (i === 0) {
      firstLabelOffsetLeft = _offsetLeft
    } else if (firstLabelOffsetLeft === _offsetLeft) {
      line++
      console.log(line + '行')
    }
  }
  // 如果大于一行则隐藏
  if (line > 2) {
    expandBtn.style = 'display: show'
  } else {
    expandBtn.style = 'display: none'
  }
  expandBtn.addEventListener('click', () => {
    const _classList = listCon.classList
    if (_classList.contains('list-expand')) {
      expandBtn.innerHTML = '展开 ∨'
    } else {
      expandBtn.innerHTML = '收起 ∧'
    }
    _classList.toggle('list-expand') // 这个更简洁
  })

</script>

解析:HTML布局就不用多说了,是个前端都知道该怎么搞,如果不知道趁早送外卖去吧,多说无益,把机会留给其他人。其次CSS应该也是比较简单的,注意的是有个前提需要先规定容器的最大高度,然后使用overflow超出隐藏,这样展开就直接去掉该属性,让标签自己撑开即可。JavaScript部分我这里没有使用啥框架,因为这块实现就是个简单的Demo所以就用纯原生写比较方便,这里我们先获取容器,然后获取容器的孩子节点(这里我们也可以直接通过className查询出所有标签元素),返回的是一个可遍历的变签对象,然后我们记录第一个标签的offsetLeft左偏移值,接下来遍历所有的标签元素,如果有与第一个标签相同的值则累加,最终line表示有几行,如果超过我们最大行数(demo超出2行隐藏)则显示展开隐藏按钮。

第二种方法:通过计算容器高度对比

原理:通过容器底部与标签top比较,如果有top值大于容器底部bottom则表示超出容器隐藏。

具体上代码:

<script>
  const listCon2 = document.querySelector('.list-con-2')
  const expandBtn2 = document.querySelector('.expand-2')
  const listCon2Height = listCon2.getBoundingClientRect().bottom
  const len2 = listCon2.children.length
  for(let i = 0; i < len2; i++) {
    const _top = listCon2.children.item(i).getBoundingClientRect().top
    // 通过top判断如果有标签大于容器bottom则隐藏
    if (_top >= listCon2Height) {
      expandBtn2.style = 'display: show'
      break
    } else {
      expandBtn2.style = 'display: none'
    }
  }
  expandBtn2.addEventListener('click', () => {
    const _classList = listCon2.classList
    // console.log(_classList)
    if (_classList.contains('list-expand')) {
      expandBtn2.innerHTML = '展开 ∨'
    } else {
      expandBtn2.innerHTML = '收起 ∧'
    }
    _classList.toggle('list-expand')
  })
</script>

解析:HTMLCSS同方法一同,不同点在于这里是通过getBoundingClientRect()方法来判断,还是遍历所有标签,不同的是如果有标签的top值大于等于了容器的bottom值,则说明了标签已超出容器,则要显示展开隐藏按钮,展开隐藏还是通过容器overflow属性来实现比较简单。

【样式二】:展开隐藏按钮和标签同级(效果图样式二)

 这种样式也是绝大部分APP产品使用的风格,不信你可以打开抖音商城或汽车之家的搜索历史,十个产品九个是这样设计的,不是这样的我倒立洗头。  这种放在同级的就相对稍微难一点,因为要把展开隐藏按钮塞到标签的最后,如果是隐藏的话就要切割标签展示数量,那下面我就带大家看看我是是如何实现的。

方法一:通过遍历高度判断

原理:同样式一的高度判断一样,通过容器底部bottom与标签top比较,如果有top值大于容器顶部bottom则表示超出容器隐藏,不同的是如何计算标签展示的长度。有个前提是按钮和标签的的宽度要做限制,最好是一行能放一个标签和按钮。

具体实现上代码:

<div id="app3">
  <div class="list-con list-con-3" :class="{'list-expand': isExpand}">
    <div class="label" v-for="item in labelArr.slice(0, labelLength)">{{ item }}</div>
    <div class="label expand-btn" v-if="showExpandBtn" @click="changeExpand">{{ !isExpand ? '展开 ▼' : '隐藏 ▲' }}</div>
  </div>
</div>


<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
  const { createApp, nextTick } = Vue
  createApp({
    props: {
      maxLine: {
        type: Number,
        default: 2
      }
    },
    data () {
      return {
        labelArr: [],
        isExpand: false,
        showExpandBtn: false,
        labelLength: 0,
        hideLength: 0
      }
    },
    mounted () {
      const labels = ['人工智能', '人工智能与应用', '行业分析与市场数据', '标签标签标签标签标签标签标签', '标签A', '啊啊啊', '宝宝贝贝', '微信', '吧啊啊', '哦哦哦哦哦哦哦哦', '人工智能', '人工智能与应用']
      
      this.labelArr = labels
      this.labelLength = labels.length
      nextTick(() => {
        this.init()
      })
    },
    methods: {
      init () {
        const listCon = document.querySelector('.list-con-3')
        const labels = listCon.querySelectorAll('.label:not(.expand-btn)')
        const expandBtn = listCon.querySelector('.expand-btn')

        let labelIndex = 0 // 渲染到第几个
        const listConBottom = listCon.getBoundingClientRect().bottom // 容器底部距视口顶部距离
        for(let i = 0; i < labels.length; i++) {
          const _top = labels[i].getBoundingClientRect().top
          if (_top >= listConBottom ) { // 如果有标签顶部距离超过容器底部则表示超出容器隐藏
            this.showExpandBtn = true
            console.log('第几个索引标签停止', i)
            labelIndex = i
            break
          } else {
            this.showExpandBtn = false
          }
        }
        if (!this.showExpandBtn) {
          return
        }
        nextTick(() => {
          const listConRect = listCon.getBoundingClientRect()
          const expandBtn = listCon.querySelector('.expand-btn')
          const expandBtnWidth = expandBtn.getBoundingClientRect().width
          const labelMaringRight = parseInt(window.getComputedStyle(labels[0]).marginRight)
          for (let i = labelIndex -1; i >= 0; i--) {
            const labelRight = labels[i].getBoundingClientRect().right - listConRect.left
            if (labelRight + labelMaringRight + expandBtnWidth <= listConRect.width) {
              this.hideLength = i + 1
              this.labelLength = this.hideLength
              break
            }
          }    
        })
      },
      changeExpand () {
        this.isExpand = !this.isExpand
        console.log(this.labelLength)
        if (this.isExpand) {
          this.labelLength = this.labelArr.length
        } else {
          this.labelLength = this.hideLength
        }
      }
    }
  }).mount('#app3')
</script>

解析:同级样式Demo我们使用vue来实现,HTML布局和CSS样式没有啥可说的,还是那就话,不行真就送外卖去比较合适,这里我们主要分析一下Javascript部分,还是先通过getBoundingClientRect()方法来获取容器的bottom和标签的top,通过遍历每个标签来对比是否超出容器,然后我们拿到第一个超出容器的标签序号,就是我们要截断的长度,这里是通过数组的slice()方法来截取标签长度,接下来最关建的如何把按钮拼接上去,因为标签的宽度是不定的,我们要把按钮显示在最后,我们并不确定按钮拼接到最后是不是会导致宽度不够超出,所以我们倒叙遍历标签,如果(最后一个标签的右边到容器的距离right值+标签的margin值+按钮的width)和小于容器宽度,则说明展示隐藏按钮可以直接拼接在后面,否则标签数组长度就要再减一位来判断是否满足。然后展开隐藏功能就通过切换原标签长度和截取的标签长度来完成即可。

方法二:通过与第一个标签左偏移值对比实现

原理:同样式一的方法原理,遍历每个标签然后通过与第一个标签左偏移值对比判断是否超出行数,然后长度截取同方法一一致。

直接上代码:

<script>
  const { createApp, nextTick } = Vue
  createApp({
    data () {
      return {
        labelList: [],
        isExpand: false,
        showExpandBtn: false,
        labelLength: 0,
        hideLength: 0
      }
    },
    mounted () {
      const labels = ['人工智能', '人工智能与应用', '行业分析与市场数据报告行业分析与市场数据报告', '标签标签标签标签标签标签标签', '标签A', '啊啊啊', '宝宝贝贝', '微信', '吧啊啊', '哦哦哦哦哦哦哦哦', '人工智能', '人工智能与应用']
      this.labelList = labels
      this.labelLength = labels.length
      
      nextTick(() => {
        this.init()
      })
      
    },
    methods: {
      init () {
        const listCon = document.querySelector('.list-con-4')
        const labels = listCon.querySelectorAll('.label:not(.expand-btn)')
        const firstLabelOffsetLeft = labels[0].getBoundingClientRect().left // 第一个标签左侧偏移量
        const labelMaringRight = parseInt(window.getComputedStyle(labels[0]).marginRight)
        let line = 0 // 几行
        let labelIndex = 0 // 渲染第几个
        for(let i = 0; i < labels.length; i++) {
          const _offsetLeft = labels[i].getBoundingClientRect().left
          if (firstLabelOffsetLeft === _offsetLeft) {
            line += 1
          }
          console.log(line, i)
          if (line > 2) {
            this.showExpandBtn = true
            labelIndex = i
            // this.labelLength = this.hideLength
            break
          } else {
            this.showExpandBtn = false
          }
        }
        if (!this.showExpandBtn) {
          return
        }
        nextTick(() => {
          const listConRect = listCon.getBoundingClientRect()
          const expandBtn = listCon.querySelector('.expand-btn')
          console.log(listConRect, expandBtn.getBoundingClientRect())
          const expandBtnWidth = expandBtn.getBoundingClientRect().width
          for (let i = labelIndex -1; i >= 0; i--) {
            console.log(labels[i])
            const labelRight = labels[i].getBoundingClientRect().right - listConRect.left
            console.log(labelRight, expandBtnWidth, labelMaringRight)
            if (labelRight + labelMaringRight + expandBtnWidth <= listConRect.width) {
              this.hideLength = i + 1
              this.labelLength = this.hideLength
              break
            }
          }    
        })
      },
      changeExpand () {
        this.isExpand = !this.isExpand
        if (this.isExpand) {
          this.labelLength = this.labelList.length
        } else {
          this.labelLength = this.hideLength
        }
      }
    }
  }).mount('#app4')
</script>

这里也无需多做解释了,直接看代码即可。

结尾

上面就是【多行标签展开隐藏】功能的基本实现原理,网上相关实现比较少,我也是只用了Javascript来实现,如果可以纯靠CSS实现,有更简单或更好的方法实现可以留言相互交流学。代码没有封装成组件,但是具有一些参考意义,用于生产可以自己去封装成组件使用,完整的代码在我的GitHub仓库。

本文转载于:

https://juejin.cn/post/7251394142683742269

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 记录--多行标签超出展开折叠功能文章来源地址https://www.toymoban.com/news/detail-515752.html

到了这里,关于记录--多行标签超出展开折叠功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • css超出显示...(单行、多行)

    效果图: 注:必须要定一个宽度。 效果图: 注:必须要定一个宽度。 以上代码就能实现上面的效果

    2024年01月20日
    浏览(49)
  • 前端vue简单实用折叠面板可以折叠收起展开内容区域

    随着技术的发展,开发的复杂度也越来越高,传统开发方式将一个系统做成了整块应用,经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改,造成牵一发而动全身。通过组件化开发,可以有效实现单独开发,单独维护,而且他们之间可以随

    2024年02月06日
    浏览(50)
  • vue实现折叠展开收缩动画

    vue项目列表折叠面板动画效果实现 element-ui之el-collapse-transition(折叠展开动画)源码解析学习 以下代码注意两点 trainsition是需要有两个值,才能产生过渡动画的,所以一开始就需要获取到box1的高度(通过scrollHeight去获取它的高度) box1收缩,其实就是把它的height改为0,超出

    2024年02月09日
    浏览(37)
  • vscode折叠展开快捷键

    1.折叠所有代码 (按住ctrl 分别点击k和0) ctrl+k,ctrl+0 2.展开所有代码 (按住ctrl 分别点击k和j)  ctrl+k,ctrl+j 3. 折叠鼠标竖线所在位置的节点以及当前节点下的子节点(递归折叠)  ctrl+k,ctrl+[ 4. 展开鼠标竖线所在位置的节点以及当前节点下的子节点(递归展开)   ctrl+k,ctrl+] 5.折

    2024年02月03日
    浏览(83)
  • Android实现超出固定行数折叠文字“查看全文“、“收起全文“

    网上有很多关于这个的代码,实现都过于复杂了,github上甚至还看到一篇文章600多行代码,结果一跑起来全是bug。还是自己写吧!!! 如果我们需要换行的 \\\"查看全文\\\"、\\\"收起全文\\\" 效果那没什么号说的,因为可以直接用两个TextView然后通过判断超过行数还是没有超过行数来判

    2024年02月13日
    浏览(28)
  • vscode折叠代码展开快捷键

    1.折叠所有代码 (按住ctrl 分别点击k和0) ctrl+k,ctrl+0 2.展开所有代码 (按住ctrl 分别点击k和j) ctrl+k,ctrl+j 3. 折叠鼠标竖线所在位置的节点以及当前节点下的子节点(递归折叠) ctrl+k,ctrl+[ 4. 展开鼠标竖线所在位置的节点以及当前节点下的子节点(递归展开) ctrl+k,ctrl+] 5.折叠除所

    2024年02月11日
    浏览(58)
  • QT(C++)-QTreeview节点折叠与展开

    最近要用QT开发项目,对QT不是很熟,就根据网上的查到的知识和自己的摸索,将一些经验和知识记录下来。方便自己后续查找。 这个博客主要是QTreeview的节点折叠和展开。

    2024年02月10日
    浏览(35)
  • 微信小程序view的折叠与展开

    在做隐藏view之前,我们可以先来了解一下微信小程序视图层的事件。 官方文档 事件 | 微信开放文档 什么是事件? 事件是视图层到逻辑层的通讯方式。 事件可以将用户的行为反馈到逻辑层进行处理。 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件

    2024年02月02日
    浏览(34)
  • css 实现超出两行、多行文字省略号显示

    在我们日常使用文字超出省略号显示,一般使用下面的方式实现,但是当有需求需要实现两行乃至多行时,该怎么实现呢。 单行省略: 多行省略: ps:需要注意的是,记得控制元素width。

    2024年02月11日
    浏览(57)
  • vue折叠展开transition动画使用keyframes实现

    需求,我正常的菜单功能有隐藏与显示功能,需要增加动画 打开的时候宽度从0到300,关闭的时候,宽度从300到0

    2024年01月25日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包