【uni-app】uni-app实现聊天页面功能——功能篇(上)

这篇具有很好参考价值的文章主要介绍了【uni-app】uni-app实现聊天页面功能——功能篇(上)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

上一篇讲到了如何布局,这一篇将讲一下如何用uni-app实现小程序聊天页面的最主要的功能——发消息后页面滚动到最底部(参考过很多文章最后找到比较适合的方法)。

其他的功能(参考微信),之后的文章会讲述到具体实现方法

  • 点击聊天框的时候,聊天框随键盘抬起且聊天消息列表滚动到最底部,但整体页面不抬起
  • 聊天框textarea根据内容自适应高度,且聊天消息列表随着聊天框的增高而滚动到最底部(说白了就是最底部的消息不会被增高的聊天框给挡住)

思路

由于我们在布局上聊天滚动用的是scroll-view,里面嵌套着一个存放消息列表的容器(如左图所示),scroll-view中的一个重要属性是scroll-top,官方文档解释设置竖向滚动条位置

当消息列表的长度超过scroll-view的高度时,它们之间的高度差就是scroll-view要滚动的距离(如右图所示)。

【uni-app】uni-app实现聊天页面功能——功能篇(上)

获取节点信息用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
		}
	})
},

但是,在实测时(小程序模拟器和真机)发现滚动的位置有时滚动不到最底部(如图所示,其实下面还有一条消息被遮住了没显示出来),有时又可以滚动到最底部。

【uni-app】uni-app实现聊天页面功能——功能篇(上)

初步怀疑是节点信息获取不准确,我就去搜了关于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部分,请看我发布的上篇文章布局篇)文章来源地址https://www.toymoban.com/news/detail-500884.html

<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转换成rpx
			rpxTopx(px){
				let deviceWidth = wx.getSystemInfoSync().windowWidth
				let 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-app】uni-app实现聊天页面功能——功能篇(上)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 三分钟完成小程序 uni-app、网站接入chatgpt实现聊天效果

    1.实现后台接口 注册laf云开发账号 https://laf.dev/ 注册一个应用后进入这个页面: 下载依赖 chatgpt 配置apiKey 写send函数 配置你的apiKey 2.uni-app小程序代码中 //封装cloud 发送消息方法 微信小程序中使用 3.实现效果 在这里插入图片描述

    2024年02月11日
    浏览(50)
  • uni-app实现图片上传功能

    效果 代码  

    2024年02月13日
    浏览(65)
  • uni-app小程序分享功能实现

    通过onShareAppMessage(OBJECT) 将小程序到分享微信聊天,onShareTimeline()将小程序分享到朋友圈。 api中的参数配置参考文档:https://uniapp.dcloud.net.cn/api/plugins/share.html#onshareappmessage 分为全局引入、单页面引两种方式 全局引入只需要在小程序main.js中引入一次,可以复用,便于维护; 单

    2024年02月05日
    浏览(96)
  • 【uni-app】通过uni-app基础组件picker实现选择日期、时间的功能示例(完整代码+图文)

    一、获取日期(基础) 二、获取日期和时间(改进)  

    2024年02月11日
    浏览(53)
  • 【uni-app微信小程序】实现支付功能

    实现微信支付功能需要在小程序后台配置支付相关信息,并且在前端代码中调用微信支付API进行支付操作。好的, uni-app微信小程序实现支付功能整体流程 大致如下: 注册微信公众平台,并完成开发者资质认证; 在微信商户平台注册商户账号,并完成商户资质认证; 在商户

    2024年02月13日
    浏览(95)
  • Uni-app实现左右滑动页面内容切换(兼容微信小程序)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档         前言         整体思路         一、HTML部分         二、Script部分         三、Style部分           (先声明哦我可不是偷懒,只是想学术借鉴一下)因为最近有在做左右滑动功能,

    2024年02月07日
    浏览(95)
  • 【uni-app2.0】实现登录页记住密码功能

    使用uni-app的 uni.setStorageSync() 和 uni.getStorageSync() 方法来存储和读取密码 在登录页中添加一个记住密码的 u-checkbox 选项,并在data里面添加一个 rememberPwd 的布尔值,在每次点击记住密码 change 的时候来记录用户的选择 在点击登录按钮执行的事件中,使用 uni.setStorageSync() 方法将【

    2024年02月15日
    浏览(54)
  • uni-app 实现navigateBack返回修改前一页面数据(H5、APP、小程序)

    先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7 深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前! 因此收集整理了一份《2024年最新Web前端全套学习资料》,

    2024年04月29日
    浏览(61)
  • uni-app实现 app 小程序 手机端H5扫码功能

    首先 扫码这个功能小程序和App都是有现成的方法 但是H5是不行的 我们可以看这样一段代码 这里 我们用了条件编译 App和小程序中的代码是 一样的 他们都可以正常执行scanCode进行扫码 至于H5手机端界面 我用web-view套了个百度的链接进来 其实 大家可以参考我的文章 vue实现二维

    2024年02月11日
    浏览(56)
  • 如何在uni-app小程序端实现长按复制功能

    在开发小程序应用中,常常需要使用到长按复制功能。本文将介绍如何在uni-app小程序端实现长按复制功能。 uni-app是一个跨平台的开发框架,可以基于vue.js语法开发小程序、H5、APP等多个平台的应用。uni-app提供了一些内置组件和API,可以方便地实现各种功能。其中,uni.setCl

    2024年02月05日
    浏览(91)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包