前言
要在微信小程序中开发一个聊天会话的功能,需求中有这样的一条:要将聊天消息定位到首个未读消息。看到这样的需求灵机一动:首先想到就是把聊天消息放到滚动容器中,然后根据已读的消息设置滚动条的滚动高度,如此一来就可以定位到未读消息啦。
wx.createSelectorQuery、SelectorQuery与NodesRef
可是这个解决方案中的关键点时啥啊?想一想,无非就是要知道那些已读消息的高度。那么微信中有没有相关的API可以获取到wxml中元素(组件)的高度呢?还真有,那就是wx.createSelectorQuery。
温馨提示:下面的内容文字较多,可以看完后面的例子再回来看本部分内容!
- SelectorQuery SelectorQuery.in(Component component):将选择器的选取范围更改为自定义组件 component 内。
- NodesRef SelectorQuery.select(string selector):在当前页面下选择第一个匹配选择器 selector 的节点。返回一个 NodesRef 对象实例,可以用于获取节点信息。
- NodesRef SelectorQuery.selectAll(string selector):在当前页面下选择匹配选择器 selector 的所有节点。
- NodesRef SelectorQuery.selectViewport():选择显示区域。可用于获取显示区域的尺寸、滚动位置等信息。
- NodesRef SelectorQuery.exec(function callback):执行所有的请求。请求结果按请求次序构成数组,在 callback 的第一个参数中返回。
我们看到对于select、selectAll、selectViewport还有exec方法都返回NodesRef类型的对象,它是用于获取 WXML 节点信息的对象,我们看一下这个类的实例可以调用的一个重要的方法:
- SelectorQuery NodesRef.boundingClientRect(NodesRef.boundingClientRectCallback callback):添加节点的布局位置的查询请求。相对于显示区域,以像素为单位。其功能类似于 DOM 的 getBoundingClientRect。返回 NodesRef 对应的 SelectorQuery 。
阅读以上内容我们需要注意:SelectorQuery实例的select、selectAll、selectViewport方法调用后会返回NodesRef的实例,NodesRef实例的boundingClientRect方法调用后又会返回SelectorQuery实例。这也就是本文中接下来介绍的演示代码中可以链式调用的原因。
代码示例
如下所示:在data中定义了scrollTop用于控制scroll-view组件的滚动高度;定义了blockList数组用于循环渲染出view组件从而来模拟聊天消息,注意这里定义了9个已读消息,10个未读消息。
data: {
scrollTop: 0,
blockList: [
{
content: '1',
hasRead: true
},
//....
{
content: '9',
hasRead: true
},
{
content: '10',
hasRead: false
},
//....
{
content: '20',
hasRead: false
},
]
},
如下所示的wxml代码中,在scroll-view组件中嵌套了一个固定的view组件和用wx:for指令循环生成的一组view组件。注意对于循环生成的view组件我们为其绑定了动态的class,如果是已读消息则class类名为read-class,如果是未读消息则class类名为unread-class:
<!--pages/test/test.wxml
<view class="test-container">这是页面主体
<scroll-view class="test-scroll" scroll-top="{{scrollTop}}" scroll-y="true" bindscrolltolower="loadMore">
<view class="block-read" >我是测试内容块</view>
<view wx:for="{{blockList}}" class="{{item.hasRead ? 'read-class': 'unread-class'}}" >
{{item.content}}
</view>
</scroll-view>
</view>
如下所示的css代码中为固定的view组件定义了灰色(#ccc)的边框,为循环生成的代表已读消息的view组件定义了绿色边框,为循环生成的代表未读消息的view组件定义了红色边框:
.block-read {
height: 400rpx;
border: 1px solid #ccc;
}
.read-class {
height: 200rpx;
border: 1px solid green;
}
.unread-class {
height: 180rpx;
border: 1px solid red;
}
.test-scroll {
height: 700px;
}
以上代码的执行效果如下图所示:
首先使用select选中未读消息,代码如下图所示:
getViewHeight() {
const query = wx.createSelectorQuery().in(this)
query.select('.read-class').boundingClientRect((res:any) => {
console.log(res)
}).exec()
},
由于select只会在当前页面下选择第一个匹配选择器的节点,所以可以打印出一个节点的信息,如下图所示:
getViewHeight() {
const query = wx.createSelectorQuery().in(this)
query.selectAll('.read-class').boundingClientRect((res:any) => {
console.log(res)
}).exec()
},
selectAll可以在当前页面下选择匹配选择器的所有节点,所以可以打印出一个数组,如下图所示
getViewHeight() {
const query = wx.createSelectorQuery().in(this)
query.selectAll('.read-class').boundingClientRect((res:any) => {
let scrollTop = 0
res.forEach((item: any) => {
scrollTop = item.height
})
console.log(scrollTop)
this.setData({
scrollTop:scrollTop
})
}).exec()
},
onLoad() {
this.getViewHeight()
},
代码执行效果如下图所示:
const query = wx.createSelectorQuery().in(this)
query.selectViewport().boundingClientRect((res) => {
console.log(res)
}).exec()
selectViewport会选择显示区域,可用于获取显示区域的尺寸、滚动位置等信息,代码执行结果如下图所示:
- 要将聊天消息定位到首个未读消息的需求可以把聊天消息放到滚动容器中,然后根据已读的消息设置滚动条的滚动高度。
- scroll-view组件的scroll-top属性用于设置竖向滚动条位置。
- wx.createSelectorQuery方法调用后会返回一个 SelectorQuery 对象实例,SelectorQuery对象实例用于查询节点信息,提供了select、selectAll、selectViewport等方法。
- NodesRef类型的对象是用于获取 WXML 节点信息的对象,可以调用boundingClientRect来查询节点的布局位置。
本文出至:学新通技术网
标签: