admin 管理员组文章数量: 887021
【uni
文章目录
- 前言
- 思路
- 坑
- 代码实现
前言
上一篇讲到了如何布局,这一篇将讲一下如何用uni-app实现小程序聊天页面的最主要的功能——发消息后页面滚动到最底部(参考过很多文章最后找到比较适合的方法)。
其他的功能(参考微信),之后的文章会讲述到具体实现方法
- 点击聊天框的时候,聊天框随键盘抬起且聊天消息列表滚动到最底部,但整体页面不抬起
- 聊天框textarea根据内容自适应高度,且聊天消息列表随着聊天框的增高而滚动到最底部(说白了就是最底部的消息不会被增高的聊天框给挡住)
思路
由于我们在布局上聊天滚动用的是scroll-view
,里面嵌套着一个存放消息列表的容器(如左图所示),scroll-view中的一个重要属性是scroll-top
,官方文档解释设置竖向滚动条位置。
当消息列表的长度超过scroll-view的高度时,它们之间的高度差就是scroll-view要滚动的距离(如右图所示)。
获取节点信息用boundingClientRect
这个函数,具体方法可以参考官网uni.createSelectorQuery() | uni-app官网 (dcloud.net.cn)
坑
原本js部分的代码是这样写的:
scrollToBottom(){let query = uni.createSelectorQuery().in(this);// 获取节点信息query.select('#scrollview').boundingClientRect();query.select('#msglistview').boundingClientRect();query.exec((res) =>{if(res[1].height > res[0].height){this.scrollTop = res[1].height - res[0].height}})
},
但是,在实测时(小程序模拟器和真机)发现滚动的位置有时滚动不到最底部(如图所示,其实下面还有一条消息被遮住了没显示出来),有时又可以滚动到最底部。
初步怀疑是节点信息获取不准确,我就去搜了关于boundingClientRect()
这个函数的相关信息,官方文档上并没有对这个问题的解释,后来找到解决方案
参考文章:微信小程序 boundingClientRect 获取元素节点位置信息不准确_LGDmar的博客-CSDN博客
问题所在:页面未渲染完成而去获取了节点信息
解决方案:
方法一:可以设置一个延时函数setTimeout
,因为我们不知道渲染的时间是多少,所以我是经过试验得出一个满足需求的延时时间。
// 滚动至聊天底部
scrollToBottom(){// 外层加一个延时函数是为了能获取到节点的准确信息setTimeout(()=>{let query = uni.createSelectorQuery().in(this);// 获取节点信息query.select('#scrollview').boundingClientRect();query.select('#msglistview').boundingClientRect();query.exec((res) =>{if(res[1].height > res[0].height){this.scrollTop = this.rpxTopx(res[1].height - res[0].height)}})},15)
},
方法二:
使用$nextTick
,意为在下次DOM更新完之后执行一个回调函数。
//滚动至聊天底部
scrollToBottom(){let query = uni.createSelectorQuery().in(this);//获取节点信息query.select('#scrollview').boundingClientRect();query.select('#msglistview').boundingClientRect();query.exec((res) =>{if(res[1].height > res[0].height){this.$nextTick(()=>{this.scrollTop = this.rpxTopx(res[1].height - res[0].height)})}})
},
代码实现
vue页面:
(如果需要参考css部分,请看我发布的上篇文章布局篇)
<template><view class="chat"><scroll-view :style="{height: `${windowHeight}rpx`}"id="scrollview"scroll-y="true" :scroll-top="scrollTop":scroll-with-animation="true"class="scroll-view"><!-- 聊天主体 --><view id="msglistview" class="chat-body"><!-- 聊天记录 --><view v-for="(item,index) in msgList" :key="index"><!-- 自己发的消息 --><view class="item self" v-if="item.userContent != ''" ><!-- 文字内容 --><view class="content right">{{item.userContent}}</view><!-- 头像 --><view class="avatar"></view></view><!-- 机器人发的消息 --><view class="item Ai" v-if="item.botContent != ''"><!-- 头像 --> <view class="avatar"></view><!-- 文字内容 --><view class="content left">{{item.botContent}}</view></view></view></view></scroll-view><!-- 底部消息发送栏 --><!-- 用来占位,防止聊天消息被发送框遮挡 --><view class="chat-bottom"><view class="send-msg"><view class="uni-textarea"><textarea v-model="chatMsg"maxlength="300":show-confirm-bar="false"auto-height></textarea></view><button @click="handleSend" class="send-btn">发送</button></view></view></view>
</template>
<script>export default {data() {return {//滚动距离scrollTop: 0,userId:'',//发送的消息chatMsg:"",msgList:[{botContent: "hello,请问我有什么可以帮助你的吗?",recordId: 0,titleId: 0,userContent: "",userId: 0},{botContent: "",recordId: 0,titleId: 0,userContent: "你好呀我想问你一件事",userId: 0},] }},computed: {windowHeight() {return this.rpxTopx(uni.getSystemInfoSync().windowHeight)}},methods: {// px转换成rpxrpxTopx(px){let deviceWidth = wx.getSystemInfoSync().windowWidthlet rpx = ( 750 / deviceWidth ) * Number(px)return Math.floor(rpx)},//滚动至聊天底部scrollToBottom(){//外层加一个延时函数是为了能获取到节点的准确信息setTimeout(()=>{let query = uni.createSelectorQuery().in(this);//获取节点信息query.select('#scrollview').boundingClientRect();query.select('#msglistview').boundingClientRect();query.exec((res) =>{if(res[1].height > res[0].height){this.scrollTop = this.rpxTopx(res[1].height - res[0].height)}})},15)},// 发送消息handleSend() {//如果消息不为空if(!this.chatMsg||!/^\s+$/.test(this.chatMsg)){let obj = {botContent: "",recordId: 0,titleId: 0,userContent: this.chatMsg,userId: 0}this.msgList.push(obj);this.chatMsg = '';}else {this.$modal.showToast('不能发送空白消息')}},}}
</script>
本文标签: uni
版权声明:本文标题:【uni 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1686569293h11523.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论