加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 资源网站 > 资源 > 正文

小程序标签展开收起功能实现

发布时间:2020-12-14 19:03:16 所属栏目:资源 来源:网络整理
导读:先看效果 主要结构 我用的mpvue,如用原生标签直接转换成原生即可 div id="labelBox" div class="label userLabel" v-for="(label,inx) in labelList" :key="inx"{{label}}/div div class="more" v-show="showLabel===1" id="moreLabel" @click="openMore" d

先看效果


主要结构

我用的mpvue,如用原生标签直接转换成原生即可

<div id="labelBox">
    <div class="label userLabel" v-for="(label,inx) in labelList" :key="inx">{{label}}</div>
    <div class="more" v-show="showLabel===1" id="moreLabel" @click="openMore">
        <div>全部{{allLabel.length}}个</div>
        <img class="icon ml5" src="/static/img/i_label_down.png" />
    </div>
    <div class="more" v-show="showLabel===2" @click="closeMore">
        <div>收起</div>
        <img class="icon ml5" src="/static/img/i_label_up.png" />
    </div>
</div>


export default { data() { return { labelList: [],// 视图显示的标签集合 allLabel: [],// 所有的标签集合 firstLabel: [],// 默认显示的标签集合 showLabel: 1,// 0 两个按钮都不显示,1 显示展开,2 显示收起 } },... }

思路
利用小程序api?NodesRef.boundingClientRect?获取节点的位置与大小信息,主要用到?width,left,246);'>right

  1. 循环所有标签(.userLabel),看是否有多行,通过所有节点的?left?去判断,如果?left?相同的有多个,就证明有多行
  2. 获取标签父级(#labelBox)的宽度?width
  3. 获取到按钮(#moreLabel)的宽度
  4. 过滤第一行节点的?right,如果与按钮的width相加小于等于父级盒子的width就保留
具体的代码 wxp为微信接口Promise化,会在之后列出用到的 export default { data() { return { labelList: [],methods: { async loadPageData(){ // 请求后台数据 const res = ... // 设置 this.allLabel = res.labes; // 记录所有的标签 this.labelList = this.allLabel; // 先插入所有表情 // 设置状态 if(this.allLabel.length>0){ await wxp.timeout(300); // 插入视图之后不会马上获取到节点信息,延迟获取 this.setLabelStauts(); } },// 设置标签状态 async setLabelStauts(){ const boxDom = await wxp.getElementById('#labelBox'); const labelDoms = await wxp.getElementsByClassName('.userLabel'); const btnDom = await wxp.getElementById('#moreLabel'); const left = labelDoms[0].left; // 分行转为二维数组 let lineArr = []; let lineIndex = -1; labelDoms.forEach(v => { if(v.left==left){ lineIndex++; lineArr[lineIndex] = []; } lineArr[lineIndex].push(v); }) // 超过一行 if(lineArr.length>1){ // 默认显示加载更多按钮 this.showLabel = 1; const firstTr = lineArr[0].filter(v => (v.right+btnDom.width+(left/15*15)) <= boxDom.width); this.firstLabel = this.allLabel.slice(0,firstTr.length); this.labelList = this.firstLabel; }else{ this.showLabel = 0; } },// 展开 openMore(){ this.showLabel = 2; this.labelList = this.allLabel; },// 收起 closeMore(){ this.showLabel = 1; this.labelList = this.firstLabel; } } }

wxp.js相关代码

/** * 延时 * @param {*} delay */ export const timeout = delay => new Promise(resolve => setTimeout(resolve,delay)); /** * 根据ID获取dom的盒模型信息 * @param {*} id */ export const getElementById = (id='') => { return new Promise((resolve,reject) => { if ((typeof id).toLowerCase() !=='string'){ const err = { errMsg: '请输入字符串,例如 #box' } reject(error(err.errMsg,err)); } else if (id.indexOf('#') < 0) { const err = { errMsg: '请输入ID,例如 #box' } reject(error(err.errMsg,err)); }else{ var query = wx.createSelectorQuery() query.select(id).boundingClientRect(); query.selectViewport().scrollOffset(); query.exec(rect => { if (rect[0]){ let info = rect[0]; info.position = { left: rect[1].scrollLeft + info.left,top: rect[1].scrollTop + info.top }; resolve(info); }else{ const err = { errMsg: '没有获取到信息' } reject(error(err.errMsg,err)); } }) } }) } /** * 根据类名获取dom信息 * @param {*} className */ export const getElementsByClassName = (className = '') => { return new Promise((resolve,reject) => { if ((typeof className).toLowerCase() !== 'string') { const err = { errMsg: '请输入字符串,例如 .box' } reject(error(err.errMsg,err)); } else if (className.indexOf('.') < 0) { const err = { errMsg: '请输入类名,例如 .box' } reject(error(err.errMsg,err)); } else { wx.createSelectorQuery().selectAll(className).boundingClientRect(rects => { resolve(rects); }).exec(); } }) }


作者:不二很纯洁
链接:jianshu.com/p/87f3c1403

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读