通过上一篇文章https://blog.csdn.net/beekim/article/details/134176752?spm=1001.2014.3001.5501,
我们已经在vue-advanced-chat中替换掉原有的firebase,用socket.io简单的实现了聊天功能。
现在需要自义定该组件,改造成我们想要的样子:
先将比较重要的几块提取出来
1.重要模块
1.1 socket.io的封装
ws的几个事件是参考firebase的封装方式
socket.ts
import { reactive } from 'vue';
import { io, Socket } from 'socket.io-client';
console.log(import.meta.env.VITE_GLOB_CHATROBAT_URL);//这个地址我配置在.env配置文件里面的,方便维护
const wsUrl:any = import.meta.env.VITE_GLOB_CHATROBAT_URL;
class SocketService {socket: Socket;state: any;constructor() {this.state = reactive({id: '',//这里面可以自义定变量});// http://192.168.1.50:8567/// http://140.207.154.220:8567// ws://localhost:3333this.socket = io(wsUrl, {autoConnect: false, // 禁止自动连接extraHeaders: {'Access-Control-Allow-Origin': '*', // 设置跨域请求头},transports: ['websocket', 'polling', 'flashsocket'],//注意点:加上这个配置ws才可以注册到后台});connect() {this.socket.connect();console.log('socket connect');}disconnect() {this.socket.disconnect();console.log('socket disconnect');}/*** @description 房间更新* @param bn_user_name 当前登录人的邮箱 ,必传* @param callback 回调函数* @constructor*/// callback?: anyRoomUpdate(bn_user_name: string, callback?: any) {const param = {bn_user_name: bn_user_name,};console.log('ws事件room参数', param);this.socket.emit('room_update', param);//回调函数中传入最新获取到的值this.socket.on('room_update', (res) => {console.log('room列表(room_update)', res);if (typeof res !== 'string') {callback(res);}});}/*** @description 房间内的消息更新* @param roomId 房间id ,必传* @param callback 回调函数* @constructor*/MessageUpdate(roomId: string, callback?: any) {const param = {room_id: roomId,};console.log('ws事件参数', param);this.socket.emit('room_message_update', param);//回调函数中传入最新获取到的值this.socket.off('room_message_update'); //避免重复订阅this.socket.on('room_message_update', (res) => {console.log('房间消息(room_message_update)', res);if (typeof res !== 'string') {callback(res);}});}/*** @description 最后一条消息更新* @param bn_user_name 当前登录人 邮箱 ,必传* @param callback 回调函数* @constructor*/LastMessageUpdate(bn_user_name, callback?: any) {const param = {bn_user_name: bn_user_name,};//回调函数中传入最新获取到的值console.log('ws事件最后一条消息参数', param);this.socket.emit('last_message_update', param);this.socket.off('last_message_update'); //避免重复订阅this.socket.on('last_message_update', (res) => {console.log('最后一条消息(last_message_update)', res);if (typeof res !== 'string') {callback(res);}});}
}export const socketService = new SocketService();
export const socket = socketService.socket;
export const state = socketService.state;
在生命周期中使用和注销:(注意:这里一定要注销,我在测试时遇到了游览器偶尔能注册连接ws,多数情况下注册不了就是这个原因)
mounted() {socketService.connect();},unmounted() {console.log('distory');socketService.disconnect();},
1.2 自义定的监听事件(替换firebase方案)
1.2.1 listenMessages
监听房间内的消息
listenMessages(roomId) {socketService.MessageUpdate(roomId, (messages) => {if (messages) {const rawRoom = this.rooms.find((r) => r.roomId === roomId);if (rawRoom) {messages.forEach((message) => {//message是对话窗口里面的所有消息值const formattedMessage = this.formatMessage(rawRoom, message);const messageIndex = this.messages.findIndex((m) => m._id === message.id);if (messageIndex === -1) {//只有两个窗口登录人为同一个人,给某个人发消息是才会出现-1的情况// console.log('[listenMessages] new formatted message:' + JSON.stringify(formattedMessage));this.messages = this.messages.concat([formattedMessage]);} else {this.messages[messageIndex] = formattedMessage;this.messages = [...this.messages];}// this.markMessagesSeen(room, message);});}}});},
1.2.2 listenRooms
监听左侧房间list
listenRooms() {socketService.RoomUpdate(this.currentUserId, (rooms) => {rooms.forEach((room) => {const foundRoom = this.rooms.find((r) => r.roomId === room.id);if (JSON.stringify(this.rooms) !== '[]') {//判空if (foundRoom) {//正在编辑的用户,该功能暂时用不上foundRoom.typingUsers = room.typingUsers;//最后一次更新时间foundRoom.index = room.lastUpdated.seconds;