node实现在线聊天室

307 阅读2分钟

「本文正在参与技术专题征文Node.js进阶之路,点击查看详情

前言

聊天室 是主要基于 node 、Socket 实现的,node提供消息服务、Socket提供长链接通信

视图 是用 vue3.0 cdn引入

Node.js发布于2009年5月,由Ryan Dahl开发,是一个基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动、非阻塞式I/O模型,让JavaScript 运行在服务端的开发平台,它让JavaScript成为与PHP、Python、Perl、Ruby等服务端语言平起平坐的脚本语言

WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

安装node

安装教程不细说,很简单,请移步至官网 nodejs.cn/download/

创建项目

  1. 新建文件夹,命名为MSG
    mkdir MSG
  1. 初始化项目
    cd MSG
    npm init
    ...
    ...
    // 后面按提示 依次填写即可

安装依赖,socket.io

官网详情

    npm i socket.io

创建服务

添加一个 serve.js 文件

// 初始化 `app`
var app = require('http').createServer(handler)
// 通过传入 `http` (HTTP 服务器) 对象初始化了 `socket.io` 的一个实例
var io = require('socket.io')(app);
var fs = require('fs');

app.listen(3000);
// 记录用户信息 集合
let arr = {

}
// 作为 HTTP 服务器的回调函数
function handler (req, res) {
  // 读取index.html 返回(后文会介绍index.html中的内容)
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

// 然后监听 `connection` 事件来接收 sockets, 并将连接信息打印到控制台。
io.on('connection', function (socket) {
  socket.emit('init', { hello: 'world' });
  // 初始化链接 记录用户信息
  socket.on('init', function (data) {
    arr[data.id] = {
      user: data.id
    }
  });
  // 监听消息
  socket.on('msg', function (data) {
    socket.broadcast.emit('news', data);
  });
  socket.on('disconnect', function (data) {
   console.log(data)
  });
});

创建视图

添加一个 index.html 文件

引入 cdn vue

引入 socket.io.js

/socket.io/socket.io.js 启动服务后才能获取到 node serve.js

页面有点丑,没有细弄,这里 的逻辑是,初次进入页面 要填写名称,同时生成 唯一id,绑定当前用户,存入本地缓存, 待后面进入时直接读取缓存

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>聊天</title>
  <script src="https://unpkg.com/vue@next"></script>
  <script src="/socket.io/socket.io.js"></script>
</head>
<body>
  <div id="app">
    <!-- 注册 -->
    <div v-if="!setup">
     <div>名字: <input v-model="userInfo.name" /></div>
     <button @click="register">提交</button>
    </div>
    <div v-else>
       <div>uuid: {{userInfo.uuid}}</div>
      <div>user: {{userInfo.name}}</div>
      <div v-for="(item,index) in msgList" :key="index">{{item.name}}: {{item.msg}}</div>
      <div><input v-model="msg" /> <button @click="submit">提交</button></div>
    </div>
  </div>
 
<script>
const app = Vue.createApp({
  data() {
    return { 
      count: 4,
      ws:'',
      msgList:[],
      socket:null,
      msg:'',
      userInfo:{
        uuid: '',
        name:''
      },
      setup:false
    }
  },
  mounted() {
    // 检测本地缓存是否 已注册过  
    let userInfo = localStorage.getItem("userInfo");
    // 读取缓存信息
    if(userInfo){
      this.userInfo = JSON.parse(userInfo)
      this.setup = true
    }else{
    // 生成唯一id
      this.userInfo.uuid = guid()
    }
    // 建立连接
    let That = this
    this.socket = io('http://localhost:3000');
    // 监听 新消息 事件
    this.socket.on('news', (data) => {
      this.msgList = this.msgList.concat(data)
    });
  },
  methods:{
   // 发送消息
    submit(){
      if(!this.msg){
        alert('不能为空')
        return
      }
      let data = { name:this.userInfo.name, id: this.userInfo.uuid,msg:this.msg }
      this.msgList = this.msgList.concat(data)
      this.socket.emit('msg', data);
      this.msg = ''
    },
    // 注册信息
    register(){
      if(!this.userInfo.name){
        alert('不能为空')
        return
      }
      this.setup = true
      localStorage.userInfo = JSON.stringify(this.userInfo)
    }
  }
})
const vm = app.mount('#app')
// 生成唯一id
function guid() {
    function S4() {
      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}
</script>
</body>
</html>

初次写文章,有点生疏,如有不好之处,还望多多谅解