记录vue3 ts egg socket.io实现全局推送
egg端
1.安装egg-socket.io
npm i egg-socket.io -save
2.启用egg-socket.io
// 根目录config/plugin.js
module.exports = {
// socket启用
io: {
enable: true,
package: 'egg-socket.io',
},
}
3.配置egg-socket.io
// 根目录config/config.default.js
// socket配置
config.io = {
// namespace命名空间配置为
namespace: {
'/': {
// 预处理器中间件,对应的文件/app/io/middleware/auth.js, 这里可以配置多个文件, 用逗号隔开
connectionMiddleware: [ 'auth' ], // 这里我们可以做一些权限校验之类的操作
packetMiddleware: [], // 对消息做预处理
},
},
};
socket目录结构
4.配置socket路由
//app/router.js
module.exports = app => {
// socket路由, 指向app/io/controller/chat.js的index方法
app.io.of('/').route('sendMsg', app.io.controller.chat.index);
};
5.socket中间件
// auth.js
'use strict';
const room = 'default_room'; // 通道名
module.exports = () => {
return async (ctx, next) => {
// 加入通道
ctx.socket.join(room);
// 放行
await next();
};
};
6.socket控制器
'use strict';
const Controller = require('egg').Controller;
const room = 'default_room'; // 通道名,与socket中间件一致
class ChatController extends Controller {
async index() {
const { app, socket } = this.ctx;
const id = socket.id; // 连接ID
const nsp = app.io.of('/');
// 根据id给指定连接发送消息
nsp.sockets[id].emit('res', '发送成功');
// 给指定通道的成员发送消息
nsp.to(room).emit('allMsg', {
id,
msg: '你好',
});
}
}
module.exports = ChatController;
7.可在egg控制器向socket发送消息
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async add_account() {
const { app, socket } = this.ctx;
const nsp = app.io.of('/');
const id = socket.id;
const room = 'default_room';
// 给指定通道的成员发送消息
nsp.to(room).emit('allMsg', {
id,
msg: `在egg控制器发送消息`,
});
}
}
module.exports = HomeController;
第六点和第七点的区别是,第六点连接socket进行发送消息,第七点通过发送http请求发送消息
好了,这是serve端的,接下来看一下客户端的,也就是vue端
vue3+ts端
1.安装@types/socket.io-client,以及vue-socket.io
npm install @types/socket.io-client -save
npm install vue-socket.io -save
可能会有版本问题,我这里用的版本是
"@types/socket.io-client": "^1.4.34",
"vue-socket.io": "^3.0.10",
2.全局注册socket.io
// src/io/socket.ts
import socketio from 'socket.io-client'
export default {
install: (app) => {
const socketUrl = 'ws://127.0.0.1:7001' // 对应的服务器地址,socket是以ws开头的噢
// 连接socket
const socket = socketio.connect(socketUrl, {
// 使用 websocket
transports: ['websocket']
})
// vue3的全局属性,对标vue2的Vue.prototype
app.config.globalProperties.$socket = socket
// 提供数据或提供修改数据的方法,组件用inject使用数据
app.provide('socket', socket)
}
}
3.mian.ts注册socket
import { createApp } from 'vue'
import App from '@/App.vue'
import socketIo from './io/socket'
createApp(App).use(socketIo).mount('#app')
4.src/app.vue使用socket,单页面可全局收到消息
<template>
<router-view></router-view>
</template>
<script setup lang="ts">
// 这里用的是vant3.x的提示组件
import { Notify } from 'vant'
import { inject } from "vue"
// 引入全局的socket
const socket: any = inject("socket")
let socketId // 连接id,用于后面接收消息时自身不受到消息,也可在后端处理(暂时没研究)
// 监听socket连接状态
socket.on('connect', () => {
socketId = socket.id
console.log(`socket连接已建立成功 socketid: ${socket.id}`)
})
// 接收后端socket返回的消息
socket.on('allMsg', (res) => {
// 过滤自身
if (socketId == res.id) return
Notify({ type: 'primary', message: res.msg });
})
// 监听socket连接断开
socket.on('disconnect', () => {
console.log('断开连接')
})
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>
5.src/view/socket.vue发送消息
<template>
<van-button type="primary" @click="sendMsg">发送消息</van-button>
</template>
<script setup lang="ts">
import { inject } from "vue"
const socket: any = inject("socket")
socket.on('connect', () => {
console.log(`socket连接已建立成功 socketid: ${socket.id}`)
})
const sendMsg = () => {
socket.emit("sendMsg", '你好');
};
</script>
<style>
</style>
快去试试吧!
本文章参考
侵权联系删除