

标签宽度不固定,想要实现超出一行后就自动折叠,并在后面跟上折叠/展开按钮,当标签总长度不足一行时不显示按钮,超过一行时折叠并显示按钮
话不多说,直接上代码
<template> <ul class="sub-nav"> //这块的v-show显示条件是data,isFold(属于展开状态)||(或者)index(下标)<data.foldIndex(当前我所记录单行可以展示的数量) <li v-for="(item,index) in data.keywordList" :key="index" v-show="index < data.foldIndex||data.isFold" :class="data.keyword==item?'active-li sub-nav-list':'sub-nav-list'" @click="handleCutKey(item)"> {{item}} </li> <li class="btn" ref="fold" @click="data.isFold=!data.isFold" :style="data.isFold?{position:'unset'}:{position:'absolute'}"> {{data.isFold?'折叠':'展开'}}<img :style="{transform:data.isFold?'rotate(90deg)':'rotate(-90deg)'}" src="@/assets/image/返回键.png" alt=""> </li> </ul> </template> <script setup lang="ts"> const data = reactive({ // 关键词分类 keywordList: string[] = []; // 当前选中的关键词 keyword: string = ''; // 是否折叠关键词 isFold: boolean = false; // 折叠展示到的下标 foldIndex: number = 100; }) const fold = ref < HTMLElement | null > (null) onMounted(() => { getData() }) // 获取数据 const getData = () => { data.keywordList = ['热门', '人物', '萌宠', '美妆', '足球盛宴', '旅行', '汽车', '穿搭'] data.keyword = data.keywordList[0] let boxWidth = document.querySelector('.sub-nav').offsetWidth let arr = document.querySelectorAll('.sub-nav-list') let btnWidth = fold.value.offsetWidth variable(boxWidth, arr, btnWidth) .then(res => { data.foldIndex = res console.log(res) }) .catch(error => { // 此处不足一行时我将按钮隐藏了 fold.value.style.display = error console.error(error); }); } // 封装可折叠标签组件 const variable = (boxWidth: number, arr: HTMLElement[] | null, btnWidth: number) => { // boxWidth -- 盒子宽度 arr -- 要处理的dom列表 btnWidth -- 展开/折叠按钮的宽度 return new Promise((resolve, reject) => { let array = Array.from(arr) // // 求出元素叠加后的总长度 // 使用reduce方法计算总和 let sum = array.reduce((acc, obj) => { return acc + obj.offsetWidth; }, 0); if (sum > boxWidth) { // 元素总长度大于盒子宽度 let total = 0; let index = 0; for (let i = 0; i < array.length; i++) { total += array[i].offsetWidth; if (total >= boxWidth - btnWidth) { index = i; break; } } // 返回应该展示的标签数量 resolve(parseInt(index)); } else { // 元素总长度小于盒子宽度 console.log('小') reject('none'); } }); } // 切换关键词 const handleCutKey = (item: string) => { data.keyword = item } </script> <style scoped lang="scss"> .sub-nav { width: 100%; display: flex; align-items: center; flex-wrap: wrap; margin-top: 0.1rem; padding: 0 0.1rem; position: relative; li { display: flex; align-items: center; //此处记得用padding来留出和右边标签之间的距离 padding-right: .2rem; font-size: .12rem; white-space: nowrap; color: #999999; cursor: pointer; padding-bottom: .1rem; user-select: none; } .active-li { color: #E80000; padding-bottom: .1rem; } .btn { color: #5764FF; position: absolute; right: 0; top: 0; img { margin-left: 0.05rem; width: 0.06rem; transform: rotate(-90deg); } } } </style>
复制
现在单位经常会出这样的需求,有这种交互方式,功能很小,但挺麻烦,今天 索性就直接简单封装了一下,主要方法variable(),完整代码就这样,有问题评论区联系吧