测试代码:https://github.com/robinfoxnan/vue-advanced-chat-test0
控件源码:https://github.com/advanced-chat/vue-advanced-chat
先上个效果图:
这个控件就是专门为聊天而设计的,但是也有一些不足:
1)有些引用的控件已经过期了,还有些内存泄漏;
2)示例的demo使用的google的firebase存储,运行不起来;
文档写的太粗糙,所以折腾了一个上午,用内存数据测试了一下显示效果。
要点如下:
1)聊天室(会话)需要设置各种属性:
<template><vue-advanced-chatref="chat":current-user-id="currentUserId" // 当前用户ID:rooms="JSON.stringify(rooms)" // 会话列表:messages="roomMessages" // 当前会话的消息列表:menu-actions="JSON.stringify(menuActions)" // 右侧...的菜单// 消息有4个下拉菜单:message-selection-actions="JSON.stringify(messageSelectionActions)":loading-rooms="loadingRooms" // bool类型,是否正在加载会话列表:rooms-loaded="messagesLoaded" // bool类型,会话加载完毕,不在拉动加载:room-id="roomId" // 最初的会话ID:room-message="roomMessage" // 这个是个字符串,没有发现用法:messages-loaded = "true" // 消息更新完以后,设置为true则不再动画转圈@add-room="addRoom($event.detail[0])" // 添加一个会话按钮的回调@fetch-messages="fetchMessages($event.detail[0])" // 切换会话时候会触发加载消息的回调@send-message="sendMessage($event.detail[0])" // 点击发送按钮时候触发发送动作/>
</template>
2)会话的格式如下:
rooms: [{roomId: '1',roomName: '飞鸟 的聊天',avatar: icons[0],unreadCount: 1,lastUpdated: Date.now(),index: 1,lastMessage: {_id: '1',content: '在么?在么?',senderId: '1',username: '小花儿',timestamp: '10:20',saved: true,distributed: false,seen: true,new: true},users: [users["1"], users["2"]],typingUsers: [ '1' ]},{roomId: '2',roomName: '群聊',avatar: icons[1],unreadCount: 4,lastUpdated: Date.now(),index: 2,lastMessage: {_id: '2',content: '昨天我们做了一个测试……',senderId: '1',username: '飞鸟',timestamp: '10:20',saved: true,distributed: false,seen: true,new: true},users: [ users["1"], users["2"]],typingUsers: [ '2' ]}],
3)消息的格式如下:
const aMsg ={_id: '1',indexId: 1,content: '小花发送的测试消息',senderId: users["1"]._id,username: users["1"].username,avatar: users["1"].avatar,date: '13 November',timestamp: '10:20',system: false,saved: true,distributed: true,seen: true,deleted: false,failure: false,disableActions: false,disableReactions: false,};
4) 会话的消息的需要动态加载的:
// 点击了聊天会话,会触发这个回调函数,在这里加载消息fetchMessages({ room, options = {} }) {this.messagesLoaded = false;this.$emit('show-demo-options', false)if (options.reset) {//this.resetMessages()}console.log("选项:" +options);console.log("选中会话:" +room.roomId);this.roomMessages = roomMsgMap[room.roomId]this.messagesLoaded = true},
5) 发送消息动作:
带有附件的其实要先上传,上传完毕后,将远端的url赋值给url就认为是发送完毕了,不再显示动画了;否则一直转圈,显示发送中;
// 点击了发送按钮,则执行发送消息async sendMessage({ content, roomId, files, replyMessage }) {console.log("当前发送消息到对话:" + roomId );this.currentMsgSeq = this.currentMsgSeq + 1;const u = users[this.currentUserId];const message = {_id : this.currentMsgSeq.toString(),senderId: this.currentUserId,username: u.username,avatar: u.avatar,content: content,timestamp: formatDate(new Date()),date: '13 November',system: false,saved: true,distributed: true,seen: true,deleted: false,failure: false,disableActions: false,disableReactions: false,}if (files) {message.files = this.formattedFiles(files)console.log(files);}if (replyMessage) {message.replyMessage = {_id: replyMessage._id,content: replyMessage.content,sender_id: replyMessage.senderId}if (replyMessage.files) {message.replyMessage.files = replyMessage.files}}this.messagesLoaded = falseroomMsgMap[roomId].push(message);// console.log(roomMsgMap[roomId]);this.roomMessages = [...roomMsgMap[roomId]]// 注意,下面的用法不行,不刷新//this.roomMessages = roomMsgMap[roomId]console.log(this.roomMessages);this.messagesLoaded = true},formattedFiles(files) {const formattedFiles = []files.forEach(file => {const messageFile = {name: file.name,size: file.size,type: file.type,extension: file.extension || file.type,url: file.url || file.localUrl// 注意,这里设置了HTTP的图片地址后,能正确加载,证明上传完毕,上传过程就停止了,不转了//url :"https://img0.baidu.com/it/u=1746301175,572912059&fm=253&fmt=auto&app=120&f=JPEG?w=580&h=500"}if (file.audio) {messageFile.audio = truemessageFile.duration = file.duration}formattedFiles.push(messageFile)})return formattedFiles},
其他的我也没有测试呢。
有兴趣一起做即时通信的朋友可以私聊。