制作一个简易的即时聊天工具

实现简易的群聊天室

进入对应的文件夹

npm init -y  (将会生一个package.json描述当前项目的基本信息)
# 安装socket.io
npm install --save socket.io

整理业务场景与实现思路:

  1. 实现群聊。

    1. 当打开群聊页面时,建立websocket连接,每当有客户端连接成功,即当做进入该群聊天室。

    2. 点击发送按钮,可将自己写的消息,发送给服务端,由服务端转发给聊天室的所有人。

    3. 客户端接收服务端返回的消息,显示在聊天记录列表中。

  2. 统计并更新在线人数。

    1. 在服务端维护一个全局变量:count=0;用于表示当前在线人数。

    2. 服务端一旦监听到客户端连接成功,count++

    3. 服务端一旦监听到客户端连接断开,count--

    4. 只要count一有变化,就需要向所有客户端发消息(countmsg),更新在线人数。

    5. 客户端接收countmsg消息,更新人数即可。

服务器端 node.js

// 引入相关模块   监听客户端的连接
const http = require('http').createServer()
const socketio = require('socket.io')(http, { 
    cors: {  origin:'*' }  // 允许所有域名访问  
})

let count = 0
// 监听连接的建立
socketio.on('connection', function(socket){
    console.log('有客户端进来了:' + socket.id)
    
    // 更新在线人数
    count++
    socketio.emit('countmsg', count)
    // 监听socket的断开,一旦连接断开,则count--
    socket.on('disconnect', function(){
        count--
        socketio.emit('countmsg', count)
    })

    // 监听客户端发过来的消息
    socket.on('textmsg', function(data){
        socketio.emit('textmsg', data)   // 收到什么就给所有客户端都发一遍
    })
})

http.listen(5050, ()=>{
    console.log('服务器已启动...')
})

服务器端完成以后接下来就是我们的客户端,我们可以先准备一个登录页面,让用户注册自己的昵称,代码如下

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>微信聊天室</title>
        <link rel="stylesheet" href="styles/normalize.css">
        <link rel="stylesheet" href="styles/reset.css">
        <link rel="stylesheet" href="styles/chart.css">
    </head>
    <body>
        <div id="login-container">
            <div class="login-title">微信聊天室</div>
            <div class="login-user-icon">
                <img src="images/login.png" alt="">
            </div>
            <div>
                <input type="text" id="username" class="login-item login-username" placeholder="请输入聊天昵称">
            </div>
            <div>
                <input type="button" id="login" class="login-item login-button" value="登录">
            </div>
        </div>
        <script>
            login.onclick = function(){
                // 准备name与avatar名
                let name = username.value
                let avatar = Math.floor(Math.random()*100)+".jpg"
                window.location = `chart.html?name=${name}&avatar=${avatar}`
            }
        </script>
    </body>
</html>

 运行结果如下

用户登录以后就可以来到聊天界面进行聊天

如果用户没有注册昵就直接打开聊天界面就会跳转到登录页面

打开两个聊天室,进行检测

 

 聊天页面的代码如下

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>微信聊天室</title>
    <link rel="stylesheet" href="styles/normalize.css" />
    <link rel="stylesheet" href="styles/reset.css" />
    <link rel="stylesheet" href="styles/chart.css" />
  </head>
  <body>
    <div id="chart-container">
      <div class="chart-user-list" id="chart-user-list">
        <div class="user-item">
          <img src="images/avatar/15.jpg" alt="" />
          未知名
        </div>
      </div>
      <div class="chart-main-area">
        <div class="chart-main-title">
          <h1>
            微信聊天室(<span id="userNumber"></span>人)-<span
              id="currentUser"
            ></span>
          </h1>
        </div>
        <div class="chart-list" id="chart-list">
          <!-- <div class="user-logined" id="user-logined"><span id="logined-user"></span>上线了</div> -->
          <!-- <div class="chart-item">
                        <div class="user-face"><img src="images/avatar/11.jpg" alt=""></div>
                        <div class="user-message">111</div>
                    </div> -->
        </div>
        <div class="chart-form">
          <div>
            <textarea class="chart-form-message" id="message"></textarea>
          </div>
          <div>
            <input
              type="button"
              id="send"
              class="chart-form-send"
              value="发表"
            />
          </div>
        </div>
      </div>
    </div>
    <script src="scripts/socket.io.js"></script>
    <script>
      // 判断,如果不是登录过来的,则跳转回登录页面
      let search = decodeURI(window.location.search) // 拿到浏览器地址栏的查询字符串
      if (!search) {
        window.location = 'index.html'
      }
      let name = search.split('&')[0].split('=')[1]
      let avatar = search.split('&')[1].split('=')[1]
      console.log(`name:${name}    avatar:${avatar}`)
      // 更新页面中的头像与昵称
      let userInfoDiv = document.getElementById('chart-user-list')
      userInfoDiv.innerHTML = `<div class="user-item">
            <img src="images/avatar/${avatar}" alt="">
            ${name}
        </div>`

      // 建立websocket连接
      let socket = io('http://127.0.0.1:8081')
      console.log('连接成功', socket)

      // 监听服务端返回的更新人数的消息
      socket.on('countmsg', function (data) {
        userNumber.innerHTML = data //更新span,显示最新的人数
      })

      // 监听服务端返回的消息
      socket.on('textmsg', function (data) {
        console.log('服务端发回:', data)
        // 追加到聊天记录列表中
        let list = document.getElementById('chart-list')
        let html = list.innerHTML
        html += `<div class="chart-item">
                <div class="user-face"><img src="images/avatar/${data.avatar}" alt=""></div>
                <div style="font-size:0.9em;">${data.name}</div>
                <div class="user-message">${data.content}</div>
            </div>`
        list.innerHTML = html
        // dom操作,使list的滚动条持续在底部
        list.scrollTop = list.scrollHeight
      })

      // 点击发表按钮,发送消息
      send.onclick = function () {
        if (message.value && message.value.length < 30)
          //发送消息 {content:xx, name:xx, avatar:xx}
          socket.emit('textmsg', {
            content: message.value,
            name,
            avatar,
          })
        message.value = ''
      }
    </script>
  </body>
</html>

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cc980302

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值