聊聊小程序怎么实现“全文收起”功能

2023年 8月 1日 74.6k 0

小程序怎么实现“全文收起”功能?下面本篇文章小程序实现多行文本“全文收起”功能的方法,希望对大家有所帮助!

聊聊小程序怎么实现“全文收起”功能

小程序里经常会碰到需要实现多行文本”全文收起“功能,在掘金上有搜索到用纯css实现。亲测:ios很完美,andriod上的无效。

小程序社区有很多方案,目前在社区有看到一位大佬使用js动态计算告诉去实现,亲测大致有效果,测试后,在一些特殊情况下,计算会有误差,所以有更改些许代码。

一、需求

  • 位于多行文本右下角,展示”全文/收起“按钮
  • “展开”和“收起”两种状态的切换
  • 当文本不超过指定行数时,不显示”全文/收起“按钮
  • 文本显示【全文】展示状态下,更新数据,文本不被收起

二、实现思路

1、多行文本截断

主要用到用到 line-clamp,关键样式如下

.text-clamp3 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}

登录后复制

2、判断文本是否超出指定行数,显示全文 收起 按钮

编写两段文本,一段展示完整的文本A,一段展示使用 line-clamp省略后的文本B,因为B有被截取,因此B的高度相对较小。对比两段文本的高度,便可以知道文本是否超出两行

在小程序里,可以使用wx.createSelectorQuery()获取文本高度

js

const query = wx.createSelectorQuery().in(this);
query.selectAll(".showArea, .hideArea").boundingClientRect(res => {
console.log(res, 'res')
}).exec()

登录后复制

1.png

三、代码实现

1、初次版本

根据设计思路,立马上手代码

foldable.wxml

{{content}}
{{content}}

{{onFold ? unFoldText : onFoldText}}

登录后复制

foldable.js

/**
* 长文本内容展开与收起
* @param {String} content 长文本内容
* @param {Number} maxLine 最多展示行数[只允许 1-5 的正整数]
* @param {String} position 展开收起按钮位置[可选值为 left right]
* @param {Boolean} foldable 点击长文本是否展开收起
* @param { String } onFoldText 收缩时文字
* @param { String } unFoldText 展开时文字
*
*/

Component({
externalClasses: ['content-inner-class', 'fold-class'],
properties: {
content: {
type: String,
observer(val) {
if (this.data.onReady) {
this.getNodeClientReact()
}
}
},
maxLine: {
type: Number,
value: 1,
observer(value) {
if (!(/^[1-5]$/).test(value)) {
throw new Error(`maxLine field value can only be digits (1-5), Error value: ${value}`)
} else if (this.data.onReady) {
this.getNodeClientReact()
}
}
},
position: {
type: String,
value: "left"
},
foldable: {
type: Boolean,
value: true
},
// 收缩时文字
onFoldText: {
type: String,
value: "全文"
},
// 展开时文字
unFoldText: {
type: String,
value: "收起"
},
},
data: {
width: null,
onFold: false,
showFold: false,
onReady: false
},
lifetimes: {
attached() {
this.getNodeClientReact()
this.setData({
onReady: true
})
},
},
methods: {
getNodeClientReact() {
setTimeout(() => this.checkFold(), 10)
},
checkFold() {
const query = this.createSelectorQuery();
query.selectAll(".showArea, .hideArea").boundingClientRect(res => {
let showFold = res[0].height < res[1].height;
this.setData({
width: res[0].width,
showFold,
})
}).exec()
},
handleFold() {
this.setData({
onFold: !this.data.onFold
})
}
}
})

登录后复制

foldable.wxss

.content {
width: 100%;
position: relative;
overflow: hidden;
}

.contentInner {
word-break: break-all;
width: 100%;
color: #2f3033;
font-size: 30rpx;
line-height: 1.35;
}

.hideArea {
display: -webkit-box;
overflow: hidden;
position: fixed;
top: 100vh;
left: -100vw;
}

.foldInner {
padding-top: 10rpx;
color: #6676bd;
font-size: 32rpx;
}

.foldInner .fold {
cursor: pointer;
}

.text-clamp1 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}

.text-clamp2 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}

.text-clamp3 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}

.text-clamp4 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
}

.text-clamp5 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 5;
}

登录后复制

2、修复版本

正常情况下,此方法可行,但是在级别文字下,会计算错误。经过测试,可将 节点是.hideArea的内容定位在.showArea节点下可解决

foldable.wxss

.hideArea {
display: -webkit-box;
overflow: hidden;
/* position: fixed;
top: 100vh;
left: -100vw; */
position: absolute;
top: 0;
left: 0;
z-index: -1;
color: #fff;
}

登录后复制

3、增强版本

经过修复之后,本来是可以完美实现了,但是在测试过程中,第一次正常渲染是没有问题。但如果文本数据更新,会发现如果原来的文本从一行增加到两行时,使用wx.createSelectorQuery()计算的高度会有存在是实际高低的两倍的现象。导致会错误出现【全文】文字。然后文本从两行增加到三行或者多行都没问题,不太理解为什么会出现这个错误计算的现象。(期待大神能留言告知 ? )

2.png

为了弥补这个坑,我引入了lineHieght这个属性。

// foldable.js
Component({
properties: {
lineHieght: {
type: Number,
observer(value) {
if (!(/^[0-9]*$/).test(value)) {
throw new Error(`lineHieght field value can only be digits`)
}
}
}
}
})

登录后复制

通过lineHieght和最多可展示行数maxLine可以计算出,可在界面展示的最大高度。

// 文本可见的最大高度
const maxHeight = this.data.lineHieght * this.data.maxLine;

登录后复制

当然了,我们也需要适配不同的设备,而且通过wx.createSelectorQuery()计算出来的结果是以px为单位的。

所以,行高需要根据设备尺寸去改变。因为我们是以宽度是750px尺寸为设计稿的,所以根据wx.getSystemInfoSync()可以获取设备信息,进而转换成px的尺寸。

// foldable.js
changeRpxToPx(rpxInteger) {
return wx.getSystemInfoSync().windowWidth / 750 * rpxInteger
},

登录后复制

因此,更新checkFold方法

checkFold() {
const query = this.createSelectorQuery();
query.selectAll(".showArea, .hideArea").boundingClientRect(res => {
let showFold = res[0].height < res[1].height;
const lineHeightToPx = this.changeRpxToPx(this.data.LineHeight);
// 展示区域高度(即是可能会被截取的可见文字)
const showAreaHeight = res[0].height;
// 隐藏区域的高度(即是完整文本高度,偶然事件会计算错误)
const hideAreaHeight = res[1].height;
// 文本可见的最大高度
const maxHeight = lineHeightToPx * this.data.maxLine;
// 如果是一行文字,偶然计算错误,用行高判断
if (this.data.LineHeight && showAreaHeight maxHeight
}
this.setData({
width: res[0].width,
showFold,
})
}).exec()
},

登录后复制

4、最终版本

经过上一个版本,基本功能都已经实现。但是,如果文本超过最大行数,并且在展开全文的情况下,更新了文本,此时,全文/展开按钮会展示错误。

3.png

4.png

通过分析代码可知,在展开全文的状态下更新了文本,此时.showArea节点和.hideArea节点的高度一致,执行代码let showFold = res[0].height < res[1].height;,会返回false,因此按钮会消失。

因此解决方案为:

// 如果文本超出最大行数,并且是显示全文的状态下,再次更新了文字
let onFold = false
if (showAreaHeight == hideAreaHeight && showAreaHeight > maxHeight) {
showFold = true
onFold = true
}

登录后复制

所以最终版本的checkFold方法是:

checkFold() {
const query = this.createSelectorQuery();
query.selectAll(".showArea, .hideArea").boundingClientRect(res => {
let showFold = res[0].height maxHeight) {
showFold = true
onFold = true
}
this.setData({
width: res[0].width,
showFold,
onFold,
})
}).exec()
},

登录后复制

四、代码片段

经过多次测试,修改,最后附上代码片段:

https://developers.weixin.qq.com/s/GWj19vmC7oxp

各位大神如果有更好的建议,可留言哦~~~

【相关学习推荐:小程序开发教程】

以上就是聊聊小程序怎么实现“全文收起”功能的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论