0

0

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

青灯夜游

青灯夜游

发布时间:2022-03-07 19:45:28

|

5043人浏览过

|

来源于掘金社区

转载

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

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

小程序里经常会碰到需要实现多行文本”全文收起“功能,在掘金上有搜索到用纯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()计算的高度会有存在是实际高低的两倍的现象。导致会错误出现【全文】文字。然后文本从两行增加到三行或者多行都没问题,不太理解为什么会出现这个错误计算的现象。(期待大神能留言告知 ? )

BlackBox AI
BlackBox AI

AI编程助手,智能对话问答助手

下载

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) {
      showFold = hideAreaHeight > maxHeight
    }
    this.setData({
      width: res[0].width,
      showFold,
    })
  }).exec()
},

4、最终版本

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

3.png

4.png

通过分析代码可知,在展开全文的状态下更新了文本,此时.showArea节点和.hideArea节点的高度一致,执行代码let showFold = res[0].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 < 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) {
      showFold = hideAreaHeight > maxHeight
    }
    // 如果文本超出最大行数,并且是显示全文的状态下,再次更新了文字
    let onFold = false
    if (showAreaHeight == hideAreaHeight && showAreaHeight > maxHeight) {
      showFold = true
      onFold = true
    }
    this.setData({
      width: res[0].width,
      showFold,
      onFold,
    })
  }).exec()
},

四、代码片段

经过多次测试,修改,最后附上代码片段:https://developers.weixin.qq.com/s/GWj19vmC7oxp各位大神如果有更好的建议,可留言哦~~~

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

相关专题

更多
Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

44

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

58

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

11

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

65

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

75

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

21

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

35

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 3.1万人学习

Excel 教程
Excel 教程

共162课时 | 11.9万人学习

Kotlin 教程
Kotlin 教程

共23课时 | 2.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号