赞
踩
主要使用小程序云开发的watch 监听集合中符合查询条件的数据的更新事件,支持 where
, orderBy
, limit
,不支持 field。
一、云开发数据表设计
一个是用户表user :用户头像(avatarUrl)、昵称(nickName)等用户基本信息,可在授权登录时获取并保存到user表中。
一个是对话表存储message:发送者(from)、接受者(to)、消息(message数组)
消息利用云开发的push 之前添加到message数组中。
信息收发使用watch 根据from to查询监听消息改变
二、页面代码
chat.js
- const app = getApp()
- const { db, user } = app
- const User = db.collection('user')
- const Message = db.collection('message')
- const _ = db.command
- Page({
-
- /**
- * 页面的初始数据
- */
- data: {
- InputBottom: 0,
- user,
- to: '', // 发送给谁
- toInfo: {}, //接受者信息
- queueWatch: '',// 消息监听
- content: '', // 发送内容
- message: [], // 聊天信息
- scrollLast: null,
- },
-
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad({ to }) {
- this.setData({ to })
- this.getToInfo()
- },
-
- /**
- * 获取接受者信息
- */
- getToInfo() {
- const { to } = this.data
- const that = this
- User.doc(to).get({
- success: ({ data }) => {
- that.setData({ toInfo: data })
- wx.setNavigationBarTitle({
- title: '好友:' + data.nickName,
- })
- }
- })
- },
-
- /**
- * 生命周期函数--监听页面显示
- */
- onShow() {
- const { to, user } = this.data
- this.handleCreate(to, user._id)
- this.handleWatch(true)
- },
- //消息自动到底部
- getScollBottom() {
- this.setData({ scrollLast: 'lastPosition' })
- },
- //创建聊天
- handleCreate(to, from, cb) {
- Message.where({ to, from }).get({
- success: ({ data }) => {
- if (data.length == 0) {
- Message.add({
- data: { to, from, message: [] },
- success: () => {
- (typeof cb == 'function') && cb()
- }
- })
- } else (typeof cb == 'function') && cb()
- }
- })
- },
- //添加信息
- handleAddMessage(to, from, message, cb) {
- Message.where({ to, from }).update({
- data: { message: _.push(message) },
- success: ({ data }) => {
- (typeof cb == 'function') && cb()
- }
- })
- },
- // 信息发送
- handleSend() {
- const { to, user, content } = this.data
- if (!content) return
- const from = user._id
- const message = { from, content }
- const that = this
- this.handleAddMessage(to, from, message, () => {
- console.log('添加成功')
- //接受者创建对话和添加信息
- that.handleCreate(from, to, () => {
- that.handleAddMessage(from, to, message, () => {
- that.setData({ content: '' })
- })
- })
- })
- },
- /**
- * 监听值改变
- */
- handleInput(e) {
- const { name, value } = app.dataset(e)
- const obj = {}
- obj[name] = value
- this.setData(obj)
- },
- InputFocus({ detail: { height } }) {
- this.setData({ InputBottom: height })
- },
- InputBlur(e) {
- this.setData({ InputBottom: 0 })
- },
-
- /**
- * 监听消息变化
- */
- handleWatch: async function (watch) {
- let { queueWatch, to, user } = this.data
- const that = this
- if (watch && !queueWatch) { // 监听
- queueWatch = Message.where({ to, from: user._id })
- .watch({// 发起监听
- onChange: function ({ docs }) {
- const { message = [] } = docs[0] || {}
- that.setData({ message })
- that.getScollBottom()
- },
- onError: function (err) {
- console.error('the watch closed because of error', err)
- }
- })
- this.setData({ queueWatch })
- } else if (!watch && queueWatch) { // 取消监听
- await queueWatch.close()
- this.setData({ queueWatch: '' })
- }
- },
- /**
- * 生命周期函数--监听页面卸载
- */
- onHide: function () {
- this.handleWatch(false) // 取消监听
- },
- /**
- * 页面相关事件处理函数--监听用户下拉动作
- */
- onPullDownRefresh() {
-
- },
-
- /**
- * 页面上拉触底事件的处理函数
- */
- onReachBottom() {
-
- },
-
- /**
- * 用户点击右上角分享
- */
- onShareAppMessage() {
-
- }
- })
chat.wxml
- <scroll-view style="max-height: 100vh" scroll-y="true" scroll-into-view="{{scrollLast}}">
- <view class="cu-chat">
- <block wx:for="{{message}}" wx:key="index">
- <!-- 自已发送的 -->
- <view wx:if="{{user._id==item.from}}" class="cu-item self">
- <view class="main">
- <view class="content bg-green shadow">
- <text>{{item.content}}</text>
- </view>
- </view>
- <image class="cu-avatar radius" src="{{user.avatarUrl}}"></image>
- <view wx:if="{{false}}" class="date">2018年3月23日 13:23</view>
- </view>
- <!-- 别人发送的 -->
- <view wx:else class="cu-item">
- <image class="cu-avatar radius" src="{{toInfo.avatarUrl}}"></image>
- <view class="main">
- <view class="content shadow">
- <text>{{item.content}}</text>
- </view>
- </view>
- <view wx:if="{{false}}" class="date "> 13:23</view>
- </view>
- </block>
- </view>
- <view id="lastPosition" style="height: 45px;"></view>
- </scroll-view>
- <view class="cu-bar foot input" style="bottom:{{InputBottom}}+px">
- <view class="action">
- <text class="cuIcon-comment text-grey"></text>
- </view>
- <input class="solid-bottom" value="{{content}}" data-name="content" adjust-position="false" focus="false" maxlength="300" cursor-spacing="10" bindfocus="InputFocus" bindblur="InputBlur" bindinput="handleInput"></input>
- <view wx:if="{{false}}" class="action">
- <text class="cuIcon-emojifill text-grey"></text>
- </view>
- <button class="cu-btn bg-green shadow" bindtap="handleSend">发送</button>
- </view>
页面样式使用的是colorui css
三、效果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。