天天看點

微信小程式聊天室功能

小程式項目新增一聊天室功能;

控件是用該部落客的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>