• websocket+node+vite(vue)实现一个简单的聊天


    1.前端逻辑

    本项目基于之前搭建的vite环境:https://blog.csdn.net/beekim/article/details/128083106?spm=1001.2014.3001.5501

    新增一个登录页和聊天室页面

    <template>
      <div>登录页div>
      <div>
        用户名:<input type="text" placeholder="请输入用户名" v-model="username" /><br />
        <button @click="enter">进入聊天室button>
      div>
    template>
    <script setup lang="ts">
    import { onMounted, ref } from "vue";
    import { useRouter } from "vue-router";
    const username = ref();
    
    const { replace } = useRouter();
    
    onMounted(() => {
      username.value = localStorage.getItem("_username");
      if (username.value) {
        replace({ path: "/chatRoom" });
      }
    });
    
    const enter = () => {
      const _username = username.value.trim();
      if (_username.length > 0) {
        localStorage.setItem("_username", _username);//缓存当前登录人
        replace({ path: "/chatRoom" });
      }
    };
    script>
    <style scoped lang="less">style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    
    <template>
      <div>聊天室div>
      <div class="msg-list" v-if="msgList">
        <div v-for="(item, index) in msgList" :key="index">
          <div>
            <span>{{ item.user }}span>
            <span>{{ item.date }}span>
          div>
          <div>消息:{{ item.msg }}div>
        div>
      div>
      <div>
        <input type="text" placeholder="请输入消息" v-model="msg" />
        <button @click="send">发送button>
      div>
    template>
    <script setup lang="ts">
    import { ref } from "vue";
    const msgList = ref<any>([]);
    const msg = ref();
    
    const send = () => {
      if (!msg.value.trim().length) return;
    
       msgList.value.push({
         id: new Date().getTime(),
         user: localStorage.getItem("_username"),
         date: new Date(),
         msg: msg.value,
       });
    
    };
    script>
    <style scoped lang="less">style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    2.封装websocket

    const useWebSocket = (handleMessage: any) => {
      const ws = new WebSocket('ws://localhost:8000');
      const init = () => {
        bindEvent();
      };
    
      function bindEvent() {
        ws.addEventListener("open", handleOpen, false);
        ws.addEventListener("close", handleClose, false);
        ws.addEventListener("error", handleError, false);
        ws.addEventListener("message", handleMessage, false);
      }
      function handleOpen(e) {
        console.log("WebSocket open", e);
      }
      function handleClose(e) {
        console.log("WebSocket open", e);
      }
      function handleError(e) {
        console.log("WebSocket open", e);
      }
    
      init();
      return ws;
    };
    
    export { useWebSocket };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    3.后端(node)逻辑

    先在根目录建一个server文件夹,在下面建一个index.js文件(node需要js文件才可以执行,别建ts文件),然后执行以下两条命令
    在这里插入图片描述

    npm init -y
    
    yarn add ws
    
    • 1
    • 2
    • 3

    index.js

    console.log("测试websocket");
    const WebSocket = require("ws");
    ((Ws) => {
      const server = new Ws.Server({ port: 8000 });
    
      const init = () => {
        bindEvent();
      };
      function bindEvent() {
        server.on("open", handleOpen);
        server.on("close", handleClose);
        server.on("error", handleError);
        server.on("connection", handleConnection);
      }
    
      function handleOpen() {
        console.log("webscoket  open");
      }
      function handleClose() {
        console.log("webscoket  close");
      }
      function handleError() {
        console.log("webscoket  error");
      }
      function handleConnection(ws) {
        console.log("webscoket connection");
        ws.on("message", handleMsg);
      }
      function handleMsg(msg) {
        console.log(JSON.parse(msg));
        server.clients.forEach((c) => {
          c.send(msg); //广播消息
        });
      }
    
      init();
    })(WebSocket);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    4.测试

    在测试之前需启动后台
    执行node index.js
    还需调整聊天室页面的代码为:

    <template>
      <div>聊天室div>
      <div class="msg-list" v-if="msgList">
        <div v-for="(item, index) in msgList" :key="index">
          <div>
            <span>{{ item.user }}span>
            <span>{{ item.date }}span>
          div>
          <div>消息:{{ item.msg }}div>
        div>
      div>
      <div>
        <input type="text" placeholder="请输入消息" v-model="msg" />
        <button @click="send">发送button>
      div>
    template>
    <script setup lang="ts">
    import { ref } from "vue";
    import { useWebSocket } from "@/hooks/index";
    const msgList = ref<any>([]);
    const msg = ref();
    
    // {
    //   id: new Date().getTime(),
    //   user:localStorage.getItem('_username'),
    //   date:new Date().getTime(),
    //   msg:'bbbbb'
    // }
    const handleMessage = (e) => {
      console.log(e);
      // const _msgData = JSON.parse(e.data);
      // console.log(_msgData);
    
    //因为从后台接收到的数据是blob类型的值,所以转换一下
      e.data.text().then((v) => {
        console.log(v);
        msgList.value.push(JSON.parse(v));
      });
      // msgList.value.push(_msgData);
    };
    const ws = useWebSocket(handleMessage);
    
    const send = () => {
      if (!msg.value.trim().length) return;
    
      //   msgList.value.push({
      //     id: new Date().getTime(),
      //     user: localStorage.getItem("_username"),
      //     date: new Date(),
      //     msg: msg.value,
      //   });
      ws.send(
        JSON.stringify({
          id: new Date().getTime(),
          user: localStorage.getItem("_username"),
          date: new Date(),
          msg: msg.value,
        })
      );
    };
    script>
    <style scoped lang="less">style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    开启两个窗口就可以测试了,可以基于此代码优化各种细节

  • 相关阅读:
    Vue3 国际化i18n
    【C语言】文件操作
    [Js进阶]axios简要全局封装
    第5章 dockerfile
    利用噪声构建美妙的 CSS 图形
    Spring Boot面试必问:启动流程
    linux之权限管理命令
    短视频矩阵系统源码技术独立部署搭建
    SpringBoot SpringBoot 运维实用篇 2 配置高级 2.2 临时属性【开发环境】
    Java面试题整理面向对象
  • 原文地址:https://blog.csdn.net/beekim/article/details/133851901