基於express和socket.io的超簡易版聊天室

huahua-chen發表於2017-09-01

Chat

簡易版聊天室

技術棧

  1. express
  2. socket.io

功能

  1. 實現

    • 實時聊天
    • 建立房間
    • 表情包
  2. 完善

    • 私聊

效果

登入

login
login

服務端判斷之前是否登入過聊天室,如果是則直接進入聊天室,否則跳轉到登入頁面。

app.get('/', function (req, res, next) {
  if (req.cookies.name) {
    router.showIndex(req, res, next);
  } else {
    res.redirect('/login');
  }
});複製程式碼

聊天

talk
talk

客戶端傳送訊息,並接收服務端發來的訊息

// 傳送訊息
$('.send_btn').click(sendMsg)

function sendMsg () {
  // 判斷訊息訊息是否為空
  let content = info.text().trim();
  if (!content) {
    alert('請輸入內容')
    return;
  }

  // 傳送訊息後清空文字
  info.text('').focus();
  socket.emit('send msg', content);

  // 將自己傳送的訊息新增到訊息列表當中
  let li_info = $('<li class="info mine_info"></li>');
  let span_time = $(`<span class="info_time mine_info_time">${getTime()}</span>`)
  let p_user = $('<p class="info_user mine_info_user"></p>').text($.cookie('name')).prepend(span_time);
  let p_content = $('<p class="info_content mine_info_content"></p>').text(content);

  li_info.append(p_user).append(p_content);
  msg.append(li_info);
}

// 監聽來自同一房間發來的訊息
socket.on('send msg', function (info) {
  // 將傳送過來的訊息新增到訊息列表中
  let li_info = $('<li class="info"></li>');
  let span_time = $(`<span class="info_time others_info_time">${info.time}</span>`)
  let p_user = $('<p class="info_user others_info_user"></p>').text(info.name).append(span_time);
  let p_content = $('<p class="info_content others_info_content"></p>').text(info.content);

  li_info.append(p_user).append(p_content);
  msg.append(li_info);
})複製程式碼

服務端監聽客戶端發來的訊息,並將接受到的訊息轉發給同一房間中的客戶端

socket.on('send msg', function (content) {
  // 傳送訊息給同一房間的客戶端
  socket.to(socket.room).emit('send msg', {
    name: socket.user,
    content: content,
    time: common.getTime()
  })
})複製程式碼

建立房間

room
room

建立房間可以分為兩步:使用者建立房間,使用者切換至新的房間。

客戶端傳送建立房間和切換房間的事件給服務端。

// 新增房間
addRoom.click(function () {
  // 對房間的判斷之類省略...

  if (roomLen > 0 && !exist) {
    socket.emit('add room', room);
    socket.emit('change room', room);
  }
})

// 重新整理使用者列表
socket.on('refresh users', function (usersName) {
  users.empty();
  for (let userName of usersName) {
    let li = $('<li></li>').text(userName);
    if (userName == $.cookie('name')) {
      li.addClass('me')
    }
    users.append(li)
  }
})

// 重新整理房間列表
socket.on('refresh rooms', function ({rooms, active}) {
  roomsList.empty();
  for (let room of Object.keys(rooms)) {
    let li_room = $(`<li data-room="${room}"></li>`);
    let span_room = $('<span class="room"></span>').text(room)
    let span_num = $(`<span class="usersNum">${rooms[room].length}人</span>`);
    if (room == active) {
      li_room.addClass('active_room');
    }

    li_room.append(span_room).append(span_num);
    roomsList.append(li_room);
  }
  // 更改標題的名稱
  now.text(active);
})複製程式碼

服務端增加、切換房間,傳送重新整理房間列表、使用者列表的事件給客戶端

// 增加房間
socket.on('add room', function (room) {
  rooms[room] = [];
})

// 切換房間
socket.on('change room', function (to) {
  // 記錄使用者離開的房間
  let from = socket.room;
  common.removeItem(rooms[from], socket.user);

  // 將使用者傳送到新的房間
  rooms[to].push(socket.user);
  socket.room = to;

  // 傳送重新整理使用者列表的訊息
  for (let i in users) {
    users[i].emit('refresh rooms', {
      rooms: rooms,
      active: users[i].room
    })
  }

  // 離開和加入新的房間
  socket.leaveAll();
  socket.join(socket.room);

  // 通知離開的房間重新整理使用者列表
  socket.to(from)
    .emit('refresh users', rooms[from]);

  // 通知進入的房間重新整理使用者列表
  io.to(socket.room)
    .emit('refresh users', rooms[socket.room]);
})複製程式碼

具體請看原始碼,謝謝!

最後

貼出來主要希望能吸收建議。點選檢視原始碼

相關文章