最近在做一个项目,需要运用到实时聊天功能,分享一下。
分为:
1.界面如何布局以及细节;
2.如何实现实时更新;
3.全部代码展示;
一、界面如何布局以及细节:
1.说到底,聊天界面就是循环一个数组,每一行为一个单位(item),循环(wx.for)我们设置的装聊天记录的数组。
2.我们设置每个item中有一个“id”来区别当前这条消息是本人发的,还是对方发的。(在连接系统后可以用两方人的_id来区分)。
数组设置为:
3.我们在很多的带有聊天功能的系统中都知道,进入页面和发送信息我们的需要将视角放置到我们刚更新的那条信息,则就有
①设置<scroll-view>中的一个叫scroll-into-view的属性为一个“toBottom”这个字段:
<scroll-view class="sv" scroll-y scroll-into-view="{{toBottom}}">
</scroll-view>
②在循环体中加上id="item{{index}}",意为:设置当前循环体的id为当前item对应下标;
③我们在js中初始化聊天内容时每次都设置toBottom为当前循环的长度减一:
this.setData({
toBottom : `item${this.data.chatContent.length - 1}`,
})
(注意:每一次为toBottom赋值时,应当与周围的this.setData({})分开,否者会赋值失败!)
二、如何实现实时更新:
首先,我们需要知道微信开发中有一个数据库监听函数:
大概就是说我们在程序中写上了这个,我们就可以在运行时实时监听数据库执行了哪些操作(当然不是所有)。你可以拿去实现一下它的实例代码,看看打印,感受一下。
三、全部代码展示:
1.wxml:
<view class="root">
<scroll-view class="sv" scroll-y scroll-into-view="{{toBottom}}">
<view class="box" wx:for="{{content}}" id="item{{index}}">
<view class="item" wx:if="{{item.id == 1}}">
<image src="{{mineAvatorSrc}}" class="mineAvatorSrc"></image>
<view class="mineTextBox">
<text class="mineText">{{item.text}}</text>
</view>
</view>
<view class="item" wx:if="{{item.id == 0}}">
<view class="himTextBox">
<text class="himText">{{item.text}}</text>
</view>
<image src="{{himAvatorSrc}}" class="himAvatorSrc"></image>
</view>
</view>
</scroll-view>
<view class="sendBar">
<input type="text" model:value="{{mess}}" class="input"/>
<view class="button" bindtap="sendMess">
<text class="buttonText">发送</text>
</view>
</view>
</view>
2.wxss:
.root {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
.sv {
background-color: white;
width: 80%;
height: 90vh;
}
.sendBar {
width: 80%;
height: 10vh;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
border: 2px solid #1E90FF;
}
.input {
background-color: white;
border: 2px solid #1E90FF;
}
.box {
width: 100%;
display: flex;
flex-direction: row;
margin-top: 2px;
margin-bottom: 2px;
}
.item {
background-color: white;
width: 100%;
min-height: 50px;
display: flex;
flex-direction: row;
align-items: center;
}
.mineText {
font-size: 12px;
color: white;
}
.himText {
font-size: 12px;
color: white;
}
.adText {
position: absolute;
margin: auto;
right: 20px;
}
.button {
background-color: #1E90FF;
width: 60px;
height: 30px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-left: 20rpx;
}
.buttonText {
font-size: 14px;
color: white;
}
.mineAvatorSrc {
height: 45px;
width: 45px;
position: relative;
margin-left: 20rpx;
}
.himAvatorSrc {
height: 45px;
width: 45px;
position: relative;
right: 20rpx;
}
.mineTextBox {
background-color: #1E90FF;
max-width: 50%;
border-radius: 15rpx;
padding-left: 5px;
padding-right: 5px;
padding-top: 5px;
padding-bottom: 5px;
margin: auto;
margin-left: 40rpx;
display: block;
text-overflow:ellipsis;
word-wrap:break-word;
}
.himTextBox {
background-color: #1E90FF;
max-width: 50%;
border-radius: 15rpx;
padding-left: 5px;
padding-right: 5px;
padding-top: 5px;
padding-bottom: 5px;
margin: auto;
margin-right: 40rpx;
display: block;
text-overflow:ellipsis;
word-wrap:break-word;
}
3.js:
const app = getApp()
const db = wx.cloud.database()
Page({
/**
* 页面的初始数据
*/
data: {
mess : '',
content : [],//聊天信息
mineAvatorSrc : '/images/user_male.jpg',
himAvatorSrc : '/images/user_female.jpg',
},
//获取格式化的时间 yyyy-mm-dd-hh:mm-ss
getFormatTime(){
let date = new Date();
let ymd = date.toISOString().substring(0,10);//年-月-日
let hms = date.toTimeString().substring(0,8);//小时-分钟-秒钟
console.log(ymd + "-" + hms);
return ymd + "-" + hms;//拼接
},
//“发送”
sendMess(){
let that = this;
let mess = that.data.mess;
let content = that.data.content;
let date = that.getFormatTime();
let id = that.data.currentId;
wx.showLoading({
title: '发送ing...',
mask: true,
success: (res) => {},
fail: (res) => {},
complete: (res) => {
db.collection('chatTest')
.doc(id)
.update({
data : {
chatContent : content.concat({
id : 0,//用户自己发送,为0
text : mess,
date : date
})
},
success:function(res){
console.log("添加成功!",res);
},
fail:function(err){
console.log("添加失败!",err);
},
complete:function(){
that.setData({
mess : '',
})
wx.hideLoading({
noConflict: true,
success: (res) => {},
fail: (res) => {},
complete: (res) => {},
})
}
})
},
})
},
//初始化数据库的字段
initChatContent(){
let that = this;
wx.showLoading({
title: '初始化数据库的字段中...',
mask: true,
success: (res) => {},
fail: (res) => {},
complete: (res) => {
db.collection('chatTest')
.add({
data : {
chatContent : [],//设置一个空的聊天循环体
},
success(res){
console.log("初始化成功!",res);
that.setData({
currentId : res._id//设置当前的id
})
},
fail(err){
console.log("初始化失败!",err);
},
complete(){
wx.hideLoading({
noConflict: true,
success: (res) => {},
fail: (res) => {},
complete: (res) => {},
})
}
})
},
})
},
//查询聊天
queryChat(){
let that = this;
wx.showLoading({
title: '查询...',
mask: true,
success: (res) => {},
fail: (res) => {},
complete: (res) => {
db.collection('chatTest')
//.doc('4efa204964219ab20003873513331ef9')
.get({
success:function(res){
console.log("查询成功!",res);
if(res.data.length == 0){
that.initChatContent();//初始化数据库字段
}
else{
that.setData({
currentId : res.data[0]._id,//设置当前的id
content : res.data[0].chatContent//赋值给当前的聊天循环体
})
//定位到最后一行
that.setData({
toBottom : `item${that.data.content.length - 1}`,
})
}
},
fail:function(err){
console.log("查询失败!",err);
},
complete:function(){
wx.hideLoading({
noConflict: true,
success: (res) => {},
fail: (res) => {},
complete: (res) => {},
})
}
})
},
})
},
//数据库的监听器
dbWatcher(){
let that = this;
db.collection('chatTest').where({
})
.watch({
onChange: function (res) {
//监控数据发生变化时触发
console.log("res:",res);
if(res.docChanges != null){
if(res.docChanges[0].dataType == "update"){//数据库监听到的内容
let length = res.docChanges[0].doc.chatContent.length;
console.log("length : ",length);
let value = res.docChanges[0].doc.chatContent[length - 1];//要增添的内容
console.log("value : ",value);
that.setData({
content : that.data.content.concat(value)
})
//定位到最后一行
that.setData({
toBottom : `item${that.data.content.length - 1}`,
})
}
}
},
onError:(err) => {
console.error(err)
}
})
},
//获取时间并格式化时间
checkDateAndTime(){
let date = new Date();
let ymd = date.toISOString().substring(0,10);//年-月-日
let time = date.toTimeString().substring(0,8);//时:分:秒
console.log("年-月-日 : ",ymd);
console.log("时:分:秒 : ",time);
let resDate = ymd + '-' + time;
console.log("resDate : ",resDate);
},
/**
* 生命周期函数--监听页面加载
*/
// 生命周期函数--监听页面加载
onLoad: function (options) {
this.dbWatcher();
this.queryChat();
},
onReady(){
},
})
现在是单人聊天,实现后你可以将wxml中的
wx:if="{{item.id == 1}}"和wx:if="{{item.id == 0}}"
还有
sendMess()中的id : 0
改一改,然后预览一下,就可以实现电脑和手机实时聊天了!
(写完的闲聊:第一次写博客,还请大家指点。)