最新要闻
- 快递电子运单调查|半数快递面单未隐藏消费者个人信息
- 环球最资讯丨在地球上 我们也有了“空间站”!全球首创
- “该有的一个也不能少”!理想ONE迎来OTA升级 新增任务大师等功能
- 1万4都拿不出来?威马汽车成失信被执行人 创始人沈晖被限高
- 全面超越特斯拉Model 3 广汽昊铂Hyper GT正式上市:21.99万起 报资讯
- 今亮点!《最终幻想16》偷盘哥后续:是个学生 证据确凿但还在嘴硬
- 泰尔股份:公司的激光产品及服务广泛应用于船舶制造、工程机械、钢结构等_当前消息
- 潼南民生村镇银行:金融助力 小葡萄“串”起致富路|今日热闻
- 世界今亮点!国产第三大晶圆代工厂晶合集成:持续提升55nm产能 40nm高压获重大成果
- 焦点!仅重500g搭载7840U!GPD新Win掌机真机现身
- 百事通!新卡来得很慢 老卡走得很快!AMD ROCm开发平台放弃Vega
- 宝马i3销量暴增 降价十万的“油改电”到底香不香 百事通
- 天天热推荐:墨西哥一市长连续2年与鳄鱼结婚:如此联姻当地已存在230年
- 渭南:纳凉晚会话交安
- 网红经济学家任泽平新动向!朋友圈宣称转型美妆博主,宣传话术暗藏玄机 环球热消息
- 三星独家手机支付技术 Galaxy手机更新后封杀MST:我国早已淘汰 天天热议
手机
光庭信息跌4.57% 2021上市超募11亿2022扣非降74% 时快讯
搜狐汽车全球快讯 | 大众汽车最新专利曝光:仪表支持拆卸 可用手机、平板替代-环球关注
- 光庭信息跌4.57% 2021上市超募11亿2022扣非降74% 时快讯
- 搜狐汽车全球快讯 | 大众汽车最新专利曝光:仪表支持拆卸 可用手机、平板替代-环球关注
- 视点!美国首位女总统即将诞生?拜登恐怕要提前下岗,美政坛迎来变局?
- 当前速递!用理想仪器实现更好的颗粒 德国新帕泰克亮相CPHI & PMEC China获好评
- 微粒贷怎么申请开通 开通方法如下
- 焦点简讯:心疼!这位40岁的云南缉毒警,已是满头白发
家电
世界热讯:记录--多行标签超出展开折叠功能
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
前言
记录分享每一个日常开发项目中的实用小知识,不整那些虚头巴脑的框架理论与原理,之前分享过抽奖功能、签字功能等,有兴趣的可以看看本人以前的分享。 今天要分享的实用小知识是最近项目中遇到的标签相关的功能,我不知道叫啥,姑且称之为【多行标签展开隐藏】功能吧,类似于多行文本展开折叠功能,如果超过最大行数则显示展开隐藏按钮,如果不超过则不显示按钮。多行文本展开与折叠功能在网上有相当多的文章了,也有许多开源的封装组件,而多行标签展开隐藏的文章却比较少,刚好最近我也遇到了这个功能,所以就单独拿出来与大家分享如何实现。
出处
【多行标签展开与隐藏】该功能我们平时可能没注意一般在哪里会有,其实最常见的就是各种APP的搜索页面的历史记录这里,下面是我从拼多多(左)和腾讯学堂小程序(右)截下来的功能样式:
(资料图片仅供参考)
其它APP一般搜索的历史记录这里都有这个小功能,比如京东、支付宝、淘宝、抖音、快手等,可能稍有点儿不一样,有的是按钮样式,有的是只有展开没有收起功能,可能我们用过了很多年平时都没有注意到这个小功能,有想了解的可以去看一看哈。如果有一天你们需要开发一个搜索页面的话产品就很有可能出这样的一个功能,接下来我们就来看看这种功能我们该如何实现。
功能实现
我们先看实现的效果图,然后再分析如何实现,效果图如下:
【样式一】:标签容器和展开隐藏按钮分开(效果图样式一)
标签容器和按钮分开的这种样式功能实现起来的话我个人觉得难度稍微简单一些,下面我们看看如何实现这种分开的功能。
第一种方法:通过与第一个标签左偏移值对比实现
原理:遍历每个标签然后通过与第一个标签左偏移值对比,如果有几个相同偏移值则说明有几个换行
具体实现上代码:
<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>
解析:HTML
和CSS
同方法一同,不同点在于这里是通过getBoundingClientRect()方法来判断,还是遍历所有标签,不同的是如果有标签的top值大于等于了容器的bottom值,则说明了标签已超出容器,则要显示展开隐藏按钮,展开隐藏还是通过容器overflow属性来实现比较简单。
【样式二】:展开隐藏按钮和标签同级(效果图样式二)
这种样式也是绝大部分APP产品使用的风格,不信你可以打开抖音商城或汽车之家的搜索历史,十个产品九个是这样设计的,不是这样的我倒立洗头。 这种放在同级的就相对稍微难一点,因为要把展开隐藏按钮塞到标签的最后,如果是隐藏的话就要切割标签展示数量,那下面我就带大家看看我是是如何实现的。
方法一:通过遍历高度判断
原理:同样式一的高度判断一样,通过容器底部bottom与标签top比较,如果有top值大于容器顶部bottom则表示超出容器隐藏,不同的是如何计算标签展示的长度。有个前提是按钮和标签的的宽度要做限制,最好是一行能放一个标签和按钮。
具体实现上代码:
<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>{{ item }}
解析:同级样式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
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
关键词:
世界热讯:记录--多行标签超出展开折叠功能
世界焦点!Linux下PAM认证详解(以centos7为例)
快递电子运单调查|半数快递面单未隐藏消费者个人信息
环球最资讯丨在地球上 我们也有了“空间站”!全球首创
“该有的一个也不能少”!理想ONE迎来OTA升级 新增任务大师等功能
1万4都拿不出来?威马汽车成失信被执行人 创始人沈晖被限高
全面超越特斯拉Model 3 广汽昊铂Hyper GT正式上市:21.99万起 报资讯
今亮点!《最终幻想16》偷盘哥后续:是个学生 证据确凿但还在嘴硬
泰尔股份:公司的激光产品及服务广泛应用于船舶制造、工程机械、钢结构等_当前消息
Linux设置字符编码 全球快播
视觉冲击力!水球图让数据一览无余_世界新消息
潼南民生村镇银行:金融助力 小葡萄“串”起致富路|今日热闻
世界今亮点!国产第三大晶圆代工厂晶合集成:持续提升55nm产能 40nm高压获重大成果
焦点!仅重500g搭载7840U!GPD新Win掌机真机现身
百事通!新卡来得很慢 老卡走得很快!AMD ROCm开发平台放弃Vega
宝马i3销量暴增 降价十万的“油改电”到底香不香 百事通
天天热推荐:墨西哥一市长连续2年与鳄鱼结婚:如此联姻当地已存在230年
渭南:纳凉晚会话交安
每日速讯:Mybatis-Plus的详细使用
天天百事通!华为扫地僧:揭秘IoT+鸿蒙帮助企业突围物联网安全问题
【新华500】新华500指数(989001)3日涨1.28% 全球热点
网红经济学家任泽平新动向!朋友圈宣称转型美妆博主,宣传话术暗藏玄机 环球热消息
三星独家手机支付技术 Galaxy手机更新后封杀MST:我国早已淘汰 天天热议
盲订超过2万台!比亚迪腾势N7即将上市 今晚21:30开启大定 独家
红魔魔灵电竞机械键盘官宣:自研主控芯片 1ms超低延迟
你做对了吗?自动扶梯上禁止行走 赶时间请走楼梯 最新
当前焦点!马斯克一年坐私人飞机超24万公里 华为李小龙:没我多
2023年椰子油行业统计数据分析:全球椰子油产量为3.51百万吨 环球今日讯
当前关注:援外日记丨在利比里亚 我们从朋友变成了兄弟姐妹
每日热点:RTX 4090烧毁无算!万恶的12VHPWR 16针接口终于要淘汰了
焦点播报:越南高考中文题曝光引热议 网友:难度不大
北大清华成才率中国最差 毁了一半人!俞敏洪称不能把人生寄托在考名牌大学上
热推荐:或为问界新LOGO:华为申请WENJIE图文商标
上海豪宅1.58亿成交 买家身份曝光:虎扑/得物创始人 身家百亿 全球最新
每日时讯!福州的成功之道
Jmeter之二_JSR223取样器,断言等添加失败的解决办法
每日速讯:科比5代多少钱_科比5代增高多少
你怎么看?21%的韩国人支持收单身税 有网友支持交 国家才能存续_环球观天下
环卫工儿子高考687分报考上海交大:关注科研 梦想攻克“卡脖子”技术|天天聚看点
全球快资讯:部分人大学生信息被非法获取,北京警方:一名毕业生被刑拘
避坑:.NET内存泄露的几种情况 每日热文
世界速讯:中国人民解放军海军博物馆预约规则
谁能想到!“白娘子”施法手势居然是赵雅芝自己设计的|世界微动态
性感掀背小翘臀!奔驰全新双门轿跑来了:CLE Coupe即将亮相 全球视讯
快讯:搭载骁龙8 Gne2稳了:三星Galaxy Z Fold5现身Geekbench数据库
俄罗斯2032年建成新一代空间站 届时国际空间站已坠毁|天天通讯
【环球新要闻】网页直播源码知识分享:“直播卫士”,查杀病毒功能在此!
环球百事通!芋泥香酥棒如何做 偷偷藏不住芋泥香酥鸭好吃不 基本情况讲解
多款新品汇聚2023MWC,AAC声光触XR全栈式解决方案成焦点 快报
韩国知名职业玩家怒批《星空》没韩语:太看不起人! 今日热议
网友自制进口豪华车国内外售价对比榜:只有特斯拉不割国人韭菜 头条
人大毕业生盗取学校学生信息建颜值打分网站 官方通报来了
天天头条:红魔首款电竞平板屏幕确定:144Hz高刷大屏 适配原生144帧游戏
谁家客户最满意?理想重回用户推荐度榜首、问界严重下滑
欧几里得空间望远镜升空 探索宇宙暗物质和暗能量
天天亮点!狂收 3K Star!一个高性能、无侵入的 Java 性能监控和统计工具,十分强悍!
【环球报资讯】Linux下轻松修改MySQL/MariaDB的Root密码
世界新动态:自学Python之路-django模板--模板继承
Linux磁盘操作:分区、格式化、挂载
2.1 Prometheus组件_观天下
世界新消息丨原来店铺照片可以造假?你点的外卖,可能来自“幽灵餐厅”
四大家电合一!石头智能洗地机A10 UltraE图赏
当前报道:微型车市场改写!比亚迪海鸥热销2.3万台:本田飞度彻底没活路
苹果MR头显未规划遥控器:主打手控和眼控
16GB再见 128GB内存满上的感觉有多爽?实测来了|全球新视野
41年大牌显卡厂商Sparkle投身Intel:三款Arc显卡开卖 千元起步
沪深股通|山推股份6月30日获外资买入0.12%股份-世界时讯
焦点速看:前端Vue自定义可自由滚动精美tabs选项卡标签栏标题栏 可设置背景颜色,
【工程报告】编程技术项目报告【编号:网页01号】
创世纪(300083.SZ):钻铣加工中心已累计出货超过90000台,成功入选2022年国家制造业单项冠军产品|环球动态
Twitter (TWTR.US) 阅读限制引发混乱,马斯克辩称是为了保护用户数据安全_每日快看
国产S80太阳能滑板车亮相:最短晒7小时充满电 可跑35公里
比亚迪高端MPV腾势D9 6月大卖超1.1万辆:连拿半年销量第一_世界今日报
0糖0卡0脂 5年福鼎老白茶:福鼎原煮白茶2.3元/瓶大促
全球聚焦:卷上天!上海交大博士应聘中学保健员 复旦附中回应
新疆哈密遭沙尘袭击 “百米沙墙”进城!附个人防沙方法
木薯资源7月3日上午起停牌 原因未知-即时
Shopee面经总结
最高检发布湿地保护公益诉讼典型案例
降价太香!特斯拉二季度交付超46.6万辆:Model 3/Y卖爆-天天快播
马斯克回应限流推特:离手机远点 多陪陪朋友和家人|天天通讯
五旬女子被喊阿姨拒买单索赔2000 服务员道歉还打折:网友感慨不能理解
快消息!留有生机!ASML官网显示:支持7nm高端DUV光刻机仍可出口
读发布!设计与部署稳定的分布式系统(第2版)笔记17_中间件、背压和调速器_焦点热闻
中央气象台发布暴雨蓝色预警 11省区市将现大到暴雨
加大债券非市场化发行监管力度
A股半年报披露将于7月中旬拉开帷幕
环球即时:【读财报】基金半年透视:上半年新发规模同比下降22.55% 招商基金、博时基金等近百只产品延募
当前快报:你还有理由不升吗?微软曝光Windows 12:设计更高级 新浮动任务栏
男生看完《消失的她》后共情大哭 女友心疼称其太善良:网友热议
天天热推荐:菌中之冠!鸡枞菌因气候减产200多元一斤 十年涨十倍:你吃过吗
25.98万起!余承东力荐全新问界M5标准版:跑长途不用充电加油
天天热议:围墙挡景?这一景区,500米“安全墙”拆了!
环球聚焦:张雪峰出院:这段时间网上很多关于我的传言都是假的
全球快讯:【项目报告】编程技术刷题报告【编号:刷题01号】
环球今头条!巴西前总统罗塞夫:中国的脱贫工作令人惊艶
环球聚焦:Intel新至强又有新接口了!功耗可达350W
巴西男子中风后患神秘“慷慨病”:给不认识的人大肆送钱-环球视点
2TB SSD还不到500块!背后的故事挺复杂 长江存储只是其一
验证码越来越抽象 我快不能证明自己是人类了|环球短讯