websocket和原生js实现实时聊天系统

因为把websocket学了点,就想自己写一个实时聊天系统,主要效果如下:


用到的东西也不多。代码粘贴在这里:

//index.js
const ws = require('nodejs-websocket')

const PORT = 3000

let names = {}
let server = ws.createServer(connect => {
  let name = ''
  // 监听用户传递过来的数据,text事件会被触发
  connect.on('text', data => {
    data = JSON.parse(data)
    if (data.isLogin) {
      // 对用户首次登录进行验证
      name = data.nickName
      if (names[name]) {
        broadcast({
          msg: '该用户名已经登录',
          Login: false
        })
      } else {
        names[name] = name
        // 通知所有人新用户进入聊天室
        broadcast({
          msg: `用户${names[name]}进入聊天室`,
          Login: true,
          names
        })
      }
    } else {
      broadcast({
        msg: data.msg,
        nickName: names[name]
      })
    }
  })

  //监听客户端关闭,close事件会被触发
  connect.on('close', () => {
    broadcast({
      msg: `用户${names[name]}离开聊天室`,
      Level: true,
      name: names[name]
    })
    names[name] = ''
  })

  //发生错误时,error会被触发
  connect.on('error', () => {

  })
})

server.listen(PORT, () => {
  console.log(`正在监听${PORT}`);
})


// 定义广播函数,给所有用户发送信息
function broadcast(msg) {
  //server.connections: 表示所有的用户
  server.connections.forEach(item => {
    item.send(JSON.stringify(msg))
  })
}
//index.html

<!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>websocket基本使用</title>
</head>
<style>
  * {
    margin: 0;
    padding: 0;
    list-style: none;
  }
  html, body {
    width: 100%;
    height: 100%;
  }
  body {
    background: url(https://z3.ax1x.com/2021/10/11/5ZqMD0.jpg) no-repeat;
    background-size: 100% 100%;
    background-position: center center;
    backdrop-filter: blur(20px);
    overflow: auto;
  }

  .login {
    width: 300px;
    height: 300px;
    border: 1px solid pink;
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    text-align: center;
  }

  .login span {
    font-size: 28px;
    color: snow;
    position: relative;
    top: 20px;
  }

  .bBox {    
    position: relative;
    top: 40px;
  }

  .loginInput {
    width: 80%;
    height: 24px;
    border: 1px solid pink;
    border-radius: 2px;
    padding-left: 3px;
    outline: none;
  }

  .box {
    position: relative;
    top: 60px;
    left: 5px;
  }
  ul {
    display: flex;
    flex-wrap: wrap;
  }
  ul>li {
    width: 50px;
    height: 50px;
    margin: 2px;
  }

  li>img {
    width: 50px;
    height: 50px;
  }

  .now {
    border: 1px solid skyblue;
  }

  .consumer {
    width: 600px;
    height: 400px;
    border: 1px solid black;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    background-color: #fff;
  }
  .showBox {
    width: 100%;
    height: 80%;
    display: flex;
    border-bottom: 1px solid black;
  }
  .content {
    flex: 1;
  }
  .userInfo {
    width: 20%;
    height: 100%;
    border-left: 1px solid black;
  }
  .userIn {
    display: flex;
    height: 20%;
  }
  .userInput {
    flex: 1;
    outline: none;
    border: none;
  }
  .userBtn {
    width: 20%;
    border: none;
  }
  .userBtn:hover {
    background-color: #ccc;
  }
</style>
<body>
  <!-- 登录 -->
  <div class="login">
    <span class="loginSpan">登录</span>
    <div class="bBox">
      <input type="text" class="loginInput" placeholder="请输入昵称">
      <button class="loginBtn">登录</button>
    </div>
    <div class="box">
      <ul>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZX7GD.png" alt=""></li>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZXbxH.png" alt=""></li>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZXTPO.png" alt=""></li>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZXIIK.png" alt=""></li>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZXLMd.png" alt=""></li>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZXOsA.png" alt=""></li>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZXXqI.png" alt=""></li>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZXvZt.png" alt=""></li>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZXxdP.png" alt=""></li>
        <li><img src="https://z3.ax1x.com/2021/10/11/5ZXzIf.png" alt=""></li>
      </ul>
    </div>
  </div>

  <!-- 聊天室 -->
  <div class="consumer" style="display: none;">
    <div class="showBox">
      <div class="content"></div>
      <div class="userInfo"></div>
    </div>
    <div class="userIn">
      <input type="text" class="userInput">
      <button class="userBtn">发送</button>  
    </div>
  </div>

  <script>
    //登录界面处理功能
    let login = document.querySelector('.login')
    let loginSpan = document.querySelector('.loginSpan')
    let loginInput = document.querySelector('.loginInput')
    let lis = document.querySelectorAll('li')
    let loginBtn = document.querySelector('.loginBtn')

    //聊天界面处理功能
    let consumer = document.querySelector('.consumer')
    let content = document.querySelector('.content')
    let userInfo = document.querySelector('.userInfo')
    let userInput = document.querySelector('.userInput')
    let userBtn = document.querySelector('.userBtn')


    let userImg = ''
    let nickName = ''
    lis.forEach(item => {
      item.addEventListener('click', event => {
        clearBoth(lis)
        event.srcElement.className = 'now'
        userImg = event.srcElement.currentSrc
      })
    })
    function clearBoth(arr) {
      arr.forEach(item => {
        item.firstChild.className = ''
      })
    }

    //创建连接
    let socket = new WebSocket('ws://localhost:3000')

    //登录按钮点击,并发送请求进行验证
    loginBtn.addEventListener('click', () => {
      nickName = loginInput.value
      socket.send(JSON.stringify({
        userImg,
        nickName,
        isLogin: true
      }))
    })
    
    //发送信息按钮点击,发送到所有人都能看到
    userBtn.addEventListener('click', () => {
      socket.send(JSON.stringify({
        msg: userInput.value,
        nickName
      }))
      userInput.value = ''
    })

    //监听从服务端发送过来的数据
    socket.onmessage = function(msg) {
      let data = JSON.parse(msg.data)
      //处理第一次登录
      if(data.Login) {
        login.style.display = 'none'
        consumer.style.display = 'block'

        // 给所有人显示新用户上线
        let dv = document.createElement('div')
        dv.innerHTML = data.msg
        dv.style.color = 'aqua'
        content.appendChild(dv)

        //在用户列表显示新用户
        //笨方法,首先将里面所有的都删了
        userInfo.innerHTML = ''
        for(let item in data.names) {
          let dvIn = document.createElement('div')
          dvIn.innerHTML = item
          dvIn.className = item
          userInfo.appendChild(dvIn)
        }
      } else if(typeof data.login === 'Boolean') {
        //处理已经登录过的用户
        alert('该用户已经登录')
      } else if(data.Level) {
        console.log(data);
        //处理有用户离开的时候
        let dv = document.createElement('div')
        dv.innerHTML = data.msg
        dv.style.color = 'red'
        content.appendChild(dv)
        //用户表删除一个用户
        //获取要被删除的用户
        let deUser = document.getElementsByClassName(data.name)[0]
        userInfo.removeChild(deUser)
      } else {
        //处理普通聊天信息的
        let dv = document.createElement('div')
        dv.innerHTML = data.nickName + ':' + data.msg
        dv.style.color = 'pink'
        content.appendChild(dv)
      }
    }
  </script>
</body>
</html>
posted @ 2021-10-12 13:12  卿六  阅读(743)  评论(0编辑  收藏  举报