Eggjs+vue3+socketIO实现实时通讯

一、eggjs后端:

1.安装插件

npm install egg-socket.io --save

2.注册plugin.js中插件

 io: {
    enable: true,
    package: "egg-socket.io",
  },

3.config.default.js中配置插件

  config.io = {
    init: {},
    namespace: {
      "/": {
        connectionMiddleware: ["connection"], //中间件名称 没有可以为空: ['']
        packetMiddleware: ["packet"],// 指定数据包中间件,可选['']
      },
    },
  };

4.创建控制器:controller文件夹下 创建一个叫chat.js的文件

const Controller = require("egg").Controller;

class ChatController extends Controller {
  async addId() {
    const { ctx, app } = this;
    const { id } = ctx.socket;
    const message = this.ctx.args[0];
    const uid = message.uid;
    await app.model.User.update(
      { connect_id: id },
      {
        where: { id: uid }, // 根据id来更新数据
      }
    );
    console.log(message, id, 2222222222);
  }
  async onChat(res) {
    const { ctx, app } = this;
    const { id } = ctx.socket;
    const message = this.ctx.args[0];
    const uid = message.uid;
    const user = await app.model.User.findByPk(uid);
    // 在这里处理前端传递过来的值
    // await this.ctx.socket.emit("chat", id);
    await app.io.to(user.connect_id).emit("chat", message.message);
  }
}
module.exports = ChatController;

5.创建socketio路由

module.exports = (app) => {
  const { io, router, controller } = app;
  io.of("/").route("chat", controller.chat.onChat);
  io.of("/").route("addId", controller.chat.addId);
}
//特别注意 route中的chat 与 addId是前端传过来的监听事件

 

二、vue3前端

1.安装依赖

npm install vue-socket.io --save

2.mainjs中引用依赖

vue3中没有this,所以通过 app.config.globalProperties 注册了一些全局属性和方法,将采用getCurrentInstance 函数来获取当前组件实例,并从中访问全局注册的方法或属性。:

  • $socket: 将创建的 VueSocketIO 实例添加到全局属性中,使得在整个 Vue 应用中都能通过 $socket 来访问 Socket.io 实例。
  • $addSockets 和 $removeSockets: 分别注册了两个全局方法,用于添加和移除 Socket.io 事件处理函数。

import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";
import VueSocketIO from "vue-socket.io";
import { registerSockets, destroySockets } from "../utils/socket"; //具体代码在后面
const socket = new VueSocketIO({
  // debug: false,
  connection: "http://localhost:7001", //后端地址
  autoConnect: false, //禁止自动连接socket,由于不需要一直连socket服务,所以这里设置关闭
  options: {
    transports: ["websocket"],
  },
});

const app = createApp(App);
app.use(createPinia());
app.use(router);
app.config.globalProperties.$socket = socket;
// 监听事件
app.config.globalProperties.$addSockets = registerSockets;
// 移除事件
app.config.globalProperties.$removeSockets = destroySockets;
app.mount("#app");

3.until下创建socket.js直接复制就好

export const registerSockets = (sockets, proxy) => {
  sockets &&
    Object.keys(sockets).forEach((t) => {
      "subscribe" !== t &&
        "unsubscribe" !== t &&
        proxy.$socket.emitter.addListener(t, sockets[t], proxy);
    });
};
export const destroySockets = (sockets, proxy) => {
  sockets &&
    Object.keys(sockets).forEach((t) => {
      proxy.$socket.emitter.removeListener(t, proxy);
    });
};

4.在组件中使用

<template>
  <div>
    <input type="text" v-model="msg" />
    <button @click="sendMessage">发送</button> 对方给你发送的消息:{{ newmsg }}
  </div>
</template>

<script setup>
import { getCurrentInstance, onBeforeUnmount, onMounted, ref } from "vue";
const { proxy } = getCurrentInstance();
const msg = ref();
const newmsg = ref();
const sockets = {
  res(data) {
    //后台返回数据
    console.log(data);
  },
  chat(data) {
    //可以根据后台添加各种事件 前提是名字和路由一样
    newmsg.value = data;
  },
};
const key = localStorage.getItem("key");
const sendMessage2 = () => {
  proxy.$socket.io.emit("addId", {
    //发送内容 数据自己决定传什么
    uid: key,
  });
};

const sendMessage = () => {
  proxy.$socket.io.emit("chat", {
    //发送内容 数据自己决定传什么
    message: msg.value,
    uid: 2,
  });
};

onMounted(async () => {
  //在onMounted中挂载事件 不挂载的话sockets里的事件好像都监听不到
  proxy.$addSockets(sockets, proxy);
  sendMessage();
  sendMessage2();
});
onBeforeUnmount(() => {
  //注销事件
  proxy.$removeSockets(sockets, proxy);
});
</script>

此文章是我踩了n多个坑才写出来的,创作不易,如有不理解的可以私信我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值