900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 微信小程序列表实现文字内容超出隐藏并显示全文/收起按钮

微信小程序列表实现文字内容超出隐藏并显示全文/收起按钮

时间:2020-05-02 15:32:41

相关推荐

微信小程序列表实现文字内容超出隐藏并显示全文/收起按钮

微信小程序列表实现文字内容超出隐藏并显示全文/收起按钮

针对这个功能,产品的需求如下

由于我们项目是教育类产品所以这里这个功能会用在发动态这里,就像微信朋友圈那样,我们叫班级圈。

用户发班级圈时,可以发布文字内容、图片、视频,文字可以输入500个字。这样的话,如果列表一次展示全部文字,如果用户真有500个文字就基本一条动态占用了整屏高度,对于用户体验来说,用户一眼看到的东西太少了,所以产品就提出了需要折叠文字需求,并说明文字需要满6行的时候折叠,并显示全文按钮,当用户点击全文按钮时要展开所有内容,当点击收起按钮又变回折叠状态。

说完需求,现在来说说问题

首先,开发过小程序的朋友都知道,小程序内部是无法操作dom的,也就是说根本没有dom这个东西。

但是,需求是需要内容满足6行,并且满足6行后才显示全文按钮,才可以操作,如果是不满足六行的,是不应该显示全文按钮的,直接正常展示就行,这里问题就来了。

如何折叠文本,让文本超出隐藏?

如果小程序不能操作dom,如何判断显示全文按钮?

我的解决方案

第一个问题

其实第一个问题不是问题,因为我们都知道文本多行超出隐藏是可以直接使用css就能解决的,所以下面我就直接贴出实现代码

display: -webkit-box;

word-break: break-all;

text-overflow: ellipsis;

overflow: hidden;

-webkit-box-orient: vertical;

-webkit-line-clamp: 7;

第二个问题

下面我们来说说第二个问题,如何去判断满足6行就显示全文按钮。

虽说小程序是不能操作dom的,但是能不能获取到dom的一些信息呢?

答案是可以的,小程序API确实提供了一套能够去获取节点上的一些信息接口,接口名叫createSelectorQuery,创建一个选择器对象,通过选择器对象提供的方法去做一些操作,这里我们需要用到选择器对象的两个方法

select('css selector')

boundingClientRect(fn)

首先,通过select去选择我们需要获取信息的节点,参数是css的选择器,只能选择单个节点,如果需要选择多个节点可使用selectAll。然后再通过boundingClientRect方法查询布局的位置请求,相对于显示区域,以像素为单位。其功能类似于DOM的getBoundingClientRect。

该方法参数可接受一个回调,回调参数接受一个查询到的信息对象,其对象有以下信息

id :节点ID

dataset: 节点的dataset

left: 节点的左边界坐标

right: 节点的右边界坐标

top:节点的上边界坐标

bottom:节点的下边界坐标

width: 节点的宽度

height: 节点的高度

下面是一个完整示例

Page({

getRect () {

wx.createSelectorQuery().select('#the-id').boundingClientRect(function(rect){

rect.id // 节点的ID

rect.dataset // 节点的dataset

rect.left // 节点的左边界坐标

rect.right // 节点的右边界坐标

rect.top // 节点的上边界坐标

rect.bottom // 节点的下边界坐标

rect.width // 节点的宽度

rect.height // 节点的高度

}).exec()

},

getAllRects () {

wx.createSelectorQuery().selectAll('.a-class').boundingClientRect(function(rects){

rects.forEach(function(rect){

rect.id // 节点的ID

rect.dataset // 节点的dataset

rect.left // 节点的左边界坐标

rect.right // 节点的右边界坐标

rect.top // 节点的上边界坐标

rect.bottom // 节点的下边界坐标

rect.width // 节点的宽度

rect.height // 节点的高度

})

}).exec()

}

})

下面说一下这个exec(),它的作用是执行所有的请求,请求结果按请求次序构成数组,在callback的第一个参数中返回出来。

以上说完了获取节点信息的方法,可能大家心中会有疑问,为什么我要提这些东西?因为我们需要判断用户现在的文本高度,所以需要获取当前用户发布的文字内容高度,通过高度去评判内容是否满足来6行。

实现

第一实现方式

我发布了一个超过六行文本动态,然后分别打印出了在安卓和ios机器上的六行高度,这样就有了判断依据,先获取当前文本高度,如果等于了六行高度就显示全文按钮,下面是代码

<text class="x-collapse-txt x-clr-dgray {{isOpen ? 'x-collapse-open' : ''}}">

{{content}}

</text>

<view class="x-collapse-btn" catchtap="open" wx:if="{{height == 133 || height == 154}}">{{!isOpen ? '全文' : '收起'}}</view>

<script>

const {pageImgHost} = getApp()

Component({

options: {

styleIsolation: 'isolated'

},

properties: {

content: {

type: String,

value: ''

}

},

data: {

pageImgHost,

height: '',

isOpen: false

},

methods: {

open () {

this.setData({

isOpen: !this.data.isOpen

})

},

getHeight (cls) {

return new Promise(resolve => {

const query = wx.createSelectorQuery().in(this)

query.select(cls).boundingClientRect(res => {

resolve(res.height)

}).exec()

})

}

},

attached () {

this.getHeight('.x-collapse-txt').then(height => {

this.setData({

height

})

})

}

})

</script>

现在如果像上面那样写是有兼容问题,就是安卓机型太多了,有的设备六行高度是不一样的,不可能给不一样高度的手机都获取一个高度写成判断,也就是说我们把判断依据的目标值写死了,这样是很要命的,所以这个就直接被pass了。

第二实现方式

经过上面暴露的问题,我们把判断的目标值写死了这样是不行的,那怎么样可以不写死呢?下面我是这样做的,我在结构里面多写了一个节点,然后定位到了看不见到地方,这个节点输入了很多文本内容,让撑满6行高度,然后通过获取高度的方式直接获取这个节点高度,这样一来我们就不管什么什么机型手机都能拿到当前这个机器上6行高度都目标值,这样一来就有了一个精准都目标值,就有了精确条件了。修改上方代码后,是这样的

<text class="x-collapse-txt x-clr-dgray {{isOpen ? 'x-collapse-open' : ''}}">

{{content}}

</text>

<text class="x-collapse-ctxt x-clr-dgray x-p">我我我我我我我我我我我我</text>

<view class="x-collapse-btn" catchtap="open" wx:if="{{height === h}}">{{!isOpen ? '全文' : '收起'}}</view>

<script>

const {pageImgHost} = getApp()

Component({

options: {

styleIsolation: 'isolated'

},

properties: {

content: {

type: String,

value: ''

}

},

data: {

pageImgHost,

height: '',

isOpen: false,

h: 0

},

methods: {

open () {

this.setData({

isOpen: !this.data.isOpen

})

},

getHeight (cls) {

return new Promise(resolve => {

const query = wx.createSelectorQuery().in(this)

query.select(cls).boundingClientRect(res => {

console.log(res.height)

resolve(res.height)

}).exec()

})

}

},

attached () {

Promise.all([

this.getHeight('.x-collapse-ctxt'),

this.getHeight('.x-collapse-txt')

]).then(([h, height]) => {

this.setData({

h,

height

})

})

}

})

</script>

<style>

.x-collapse-txt, .x-collapse-ctxt {

line-height: 40rpx;

font-size: 28rpx;

margin-top: -24rpx;

display: -webkit-box;

word-break: break-all;

text-overflow: ellipsis;

overflow: hidden;

-webkit-box-orient: vertical;

-webkit-line-clamp: 7;

}

.x-collapse-open {

display: block;

}

.x-collapse-btn-wrap {

display: flex;

justify-content: flex-end;

}

.x-collapse-btn {

font-size: 28rpx;

width: 60rpx;

line-height: 60rpx;

color: #5b6a91;

}

.x-p {

position: fixed;

top: 200%;

z-index: -10;

}

</style>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。