小程序項目新增一聊天室功能;
控件是用該博主的https://blog.csdn.net/sinat_27612147/article/details/78456363;感謝博主提供如此方便的源碼;
功能需求:
一:WebScoket鏈接
這個是要創建小程序與後臺間的連接,比較簡單,微信api都有提供;
https://developers.weixin.qq.com/miniprogram/dev/api/network-socket.html#wxclosesocket;
二、聊天室置底
本人使用該控件時發現並沒有很好的解決聊天置底問題,跟進自己想法改造下;
1、組件<scroll-view> 設置scroll-top屬性
這是我一開始的處理方式,在收到消息和發送消息時獲取聊天記錄列表,然後根據長度動態設置 scroll-top值
let chatItems = this.data.chatItems;
this.setData({
scrollTopVal:chatItems.length*60+60
}) //scrollTopVal是<scroll-view/>的scroll-top屬性值,*60是我這一個聊天記錄大概60
如果全是文字聊天這樣是可行的,但是一旦出現了圖片就不可行了。因爲圖片聊天高度是超過60的,我也不可能每次都去for聊天記錄有多少圖片,多少文字。
2、組件<scroll-view scroll-into-view="{{toView}}"> 設置scroll-into-view屬性(值應爲某子元素id(id不能以數字開頭)。設置哪個方向可滾動,則在哪個方向滾動到該元素)
根據這個屬性,我再列表的下方再添加一個<view id="toView"></view>的空標籤;然後同理在發送和接受到消息的時候
this.setData({
toView:'toView'
})
這樣我們就可以保證scroll-view可以置底了,美滋滋;
三、聊天記錄歷史
描述:我們在小程序上是不可能保存所有的聊天記錄,所以暫時是隻保存了50條記錄,超過50條咋辦?肯定是通過接口請求後臺再渲染到小程序上。原以爲很簡單,只要根據<scroll-view/>提供的 bindscrolltoupper 屬性便可實現,即滾動到頂部時觸發scrolltoupper 事件請求接口獲取數據,再將新老數據concat拼接。
問題來了:這樣一來,我們就永遠是在頂部了,看過往數據只能上拉,看完再下拉到頂部加載新的記錄;我們要實現的是像微信那樣看記錄只要一直下拉。
解決方案:依舊是用scroll-into-view屬性,我們拿到聊天記錄數據時就給第一天添加一個id,然後出發scrolltoupper事件時獲取該id,然後數據拼接完成後通過scroll-into-view回到id位置;(該方案並不優雅,還望各位大神提供更好的解決方案,謝謝)
.js
console.log('更多歷史記錄');
let store = [{type:'text',content:'測試1'},{type:'text',content:'測試2'},{type:'text',content:'測試3'},{type:'text',content:'測試4'},{type:'text',content:'測試5'},{type:'text',content:'測試6'},{type:'text',content:'測試7'},{type:'text',content:'測試8'},{type:'text',content:'測試9'},{type:'text',content:'測試10'},{type:'text',content:'測試11'},{type:'text',content:'測試12'},{type:'text',content:'測試13'}];//測試數據
let currChatItems = this.data.chatItems;
store[0].showId = new Date().getTime();//給第一條數據添加id(注:scroll-into-view的值應爲某子元素id(id不能以數字開頭))
let id='';
//列表每個有id我都添加了.prevId這個類,是爲了方便我下邊找
wx.createSelectorQuery().selectAll('.prevId').fields({
id:true,
}, function(res){
id = res[0].id;
console.log(res)
}).exec();
this.setData({
chatItems:store.concat(currChatItems),
},()=>{
this.setData({
toView:id,
loading:true
})
})
}
.wxml
<template name="chat-item">
<view id="{{item.showId?'view'+item.showId:''}}" class="{{item.showId?'prevId':''}}">
<block wx:if="{{item.type!=='custom'}}">
<template is="chat-time" data="{{showTime:item.showTime,time:item.time}}"/>
<template is="chat-word"
data="{{length:length,index:index,headUrl:item.headUrl,isMy:item.isMy,showTime:item.showTime,time:item.time,content:item.content,type:item.type,sendStatus:item.sendStatus}}"/>
</block>
<block wx:else>
<template is="chat-custom" data="{{content:item.content}}"/>
</block>
</view>
</template>