赞
踩
需求很常见,就是当一行文字过多时,显示省略号,然后显示展开两个字,点击,文字完全展示开,点击收起,回到省略形式,如下图
有了上图,应该能更好理解,让我们再来细致分析下思路:
<!-- 外层盒子,固定只显示一行 -->
<view class="outer" style="height: {{outerHeight}}{{outerHeight == 'auto' ? '' : 'px'}}">
<!-- 内层盒子,正常摆放,但是要动态添加省略号类名 -->
<view
class="inner {{ show ? '' : 'ellipsis' }} "
style="padding-right: {{ show ? '0' : paddingRight }}px;">
{{text}}
</view>
</view>
<!-- 用于获取一行高度dom -->
<view class="get-height" >
获取一行高度的盒子
</view>
上面列举了几个问题,以及解决思考,现在我们就来具体实现
首先,获取dom高度肯定是需要的,这里把它简单封装下
/**
* 获取dom信息
* **/
getHeight(selector) {
return new Promise((resolve,reject) => {
const query = wx.createSelectorQuery().in(this)
query.select(selector).boundingClientRect(function(res){
resolve(res)
}).exec()
})
},
剩下的,大概就是高度差的判断,决定是否有省略号,以及动态添加、移除css类名,这个过程不算复杂
其实还有一个问题,就是,当确定要显示省略号时,右边切换的dom是需要定位到当前行的末尾,同时,当前行业需要一个padding,而这个padding就是切换按钮的宽度,所以这里也有一点点逻辑
html
<view class="intercept" style="font-size: {{fontSize}};" > <!-- 外层盒子,固定只显示一行 --> <view class="outer" style="height: {{outerHeight}}{{outerHeight == 'auto' ? '' : 'px'}}"> <view class="inner {{ show ? '' : 'ellipsis' }} " style="padding-right: {{ show ? '0' : paddingRight }}px;"> {{text}} </view> </view> <view wx:if="{{ heightInfo.realHeight > heightInfo.baseHeight }}" class="collapse {{show ? 'collapse-fold' : ''}}" bindtap="toggle" > {{show ? '收起' : '展开'}} </view> <!-- 用于获取一行高度dom --> <view class="get-height" > 获取一行高度的盒子 </view> </view>
js
// components/interceptText/interceptText.js.js Component({ /** * 组件的属性列表 */ properties: { text: { type: String, value: '' }, fontSize: { type: String, value: '28rpx'// 单位rpx } }, /** * 组件的初始数据 */ data: { heightInfo: { baseHeight: 0, realHeight: 0 }, show: true, // 需要动态设置的外层盒子高度 outerHeight: 0, paddingRight: 0 }, lifetimes: { async attached() { this.calculateHeight() }, }, /** * 组件的方法列表 */ methods: { /** * 动态获取展开文字宽度 * 确保展开、收起文字能显示 * **/ async getCollapseWidth() { let res = await this.getHeight('.collapse') if(!res) return this.setData({ paddingRight: `${res.width}` || 30 }) }, /** * 计算高度差,判断是否有省略号 * **/ async calculateHeight() { return Promise.all([this.getHeight('.get-height'),this.getHeight('.inner')]).then((res) => { let [baseRes,realRes] = res let baseHeight = parseInt(baseRes.height || 0) let realHeight = parseInt( realRes.height || 0) if(!baseHeight || !realHeight) { this.setData({ outerHeight: 'auto', }) return } this.setData({ heightInfo: { baseHeight, realHeight }, outerHeight: baseHeight, show: !(realHeight > baseHeight) }) // 计算展开、收起 wx.nextTick(() => { this.getCollapseWidth() }) }) }, /** * 获取dom信息 * **/ getHeight(selector) { return new Promise((resolve,reject) => { const query = wx.createSelectorQuery().in(this) query.select(selector).boundingClientRect(function(res){ resolve(res) }).exec() }) }, /** * 展开状态切换 * **/ toggle() { this.setData({ show: !this.data.show, outerHeight: this.data.show ? this.data.heightInfo.baseHeight : this.data.heightInfo.realHeight }) }, } })
css
.intercept{ position: relative; } .outer{ overflow: hidden; } .get-height{ position: absolute; z-index: -9999; top: -100%; left: -100%; height: auto; } .ellipsis{ display: -webkit-box; text-overflow: ellipsis; overflow: hidden; -webkit-line-clamp: 1; -webkit-box-orient: vertical; } .collapse{ position: absolute; right: 0; bottom: 0; width: fit-content; color: #1989fa; } .collapse-fold{ position: unset; }
笔者认为,实现该功能的难点是如何判断当前行是否应该省略,这里采取一个高度差的办法,基本就没有兼容性问题,不过实际中发下,文字会有闪烁,这是因为高度都是动态计算导致的,展开、收起,可能改为插槽更合适点
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。