You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Socket.io开发的聊天应用中实现用户正在输入状态展示

聊天应用「用户正在输入」状态提示功能实现

现有聊天功能核心代码及修改方案如下:

const chatForm = document.getElementById('chat-form');
const chatMessages = document.querySelector('.chat-messages');
const roomName = document.getElementById('room-name');
const userList = document.getElementById('users');
// 新增:获取输入框元素、正在输入提示容器元素
const msgInput = document.getElementById('msg');
const typingIndicator = document.getElementById('typing-indicator');

// 从URL获取用户名和房间号
const { username, room } = Qs.parse(location.search, {
  ignoreQueryPrefix: true,
});

console.log({username, room})

const socket = io();

// 加入聊天室
socket.emit('joinRoom', { username, room });

// 获取房间和用户列表
socket.on('roomUsers', ({ room, users }) => {
  outputRoomName(room);
  outputUsers(users);
});

// 接收服务端消息
socket.on('message', (message) => {
  console.log(message);
  outputMessage(message);
  // 收到新消息时清空正在输入提示
  typingIndicator.innerText = '';

  // 自动滚动到最新消息
  chatMessages.scrollTop = chatMessages.scrollHeight;
});

// 新增:输入事件监听+防抖,避免频繁发送请求
let typingTimeout;
msgInput.addEventListener('input', () => {
  // 输入时发送正在输入事件
  socket.emit('typing', username);
  // 清空上一个超时计时器
  clearTimeout(typingTimeout);
  // 停止输入2秒后发送停止输入事件
  typingTimeout = setTimeout(() => {
    socket.emit('stopTyping', username);
  }, 2000);
});

// 新增:接收其他用户正在输入的通知
socket.on('userTyping', (typingUsername) => {
  if (typingUsername !== username) {
    typingIndicator.innerText = `${typingUsername} 正在输入...`;
  }
});

// 新增:接收其他用户停止输入的通知
socket.on('userStopTyping', (typingUsername) => {
  if (typingIndicator.innerText === `${typingUsername} 正在输入...`) {
    typingIndicator.innerText = '';
  }
});

// 消息提交监听
chatForm.addEventListener('submit', (e) => {
  e.preventDefault();

  // 获取消息内容
  let msg = e.target.elements.msg.value;
  msg = msg.trim();
  if (!msg) {
    return false;
  }

  // 提交消息时立即清空正在输入状态
  clearTimeout(typingTimeout);
  socket.emit('stopTyping', username);

  // 发送消息到服务端
  socket.emit('chatMessage', msg);

  // 清空输入框并聚焦
  e.target.elements.msg.value = '';
  e.target.elements.msg.focus();
});

// 渲染消息到DOM
function outputMessage(message) {
  const div = document.createElement('div');
  div.classList.add('message');
  const p = document.createElement('p');
  p.classList.add('meta');
  p.innerText = message.username;
  p.innerHTML += `<span>${message.time}</span>`;
  div.appendChild(p);
  const para = document.createElement('p');
  para.classList.add('text');
  para.innerText = message.text;
  div.appendChild(para);
  document.querySelector('.chat-messages').appendChild(div);
}

// 渲染房间名到DOM
function outputRoomName(room) {
  roomName.innerText = room;
}

// 渲染用户列表到DOM
function outputUsers(users) {
 console.log({users})
  userList.innerHTML = '';
  users.forEach((user) => {
    const li = document.createElement('li');
    li.innerText = user.username;
    userList.appendChild(li);
  });
}

// 离开聊天室确认
document.getElementById('leave-btn').addEventListener('click', () => {
  const leaveRoom = confirm('确定要离开聊天室吗?');
  if (leaveRoom) {
    window.location = '../index.html';
  }
});

Socket.IO服务端配套修改

需要在服务端新增对应事件的监听和广播逻辑:

io.on('connection', (socket) => {
  // 原有joinRoom、chatMessage等逻辑保持不变
  
  // 监听正在输入事件,广播给同房间其他用户
  socket.on('typing', (username) => {
    socket.to(socket.room).emit('userTyping', username);
  });

  // 监听停止输入事件,广播给同房间其他用户
  socket.on('stopTyping', (username) => {
    socket.to(socket.room).emit('userStopTyping', username);
  });
})

页面补充

在HTML的消息列表下方、输入框上方添加提示容器即可:

<div id="typing-indicator" style="color:#999;font-style:italic;padding:0 15px 8px;"></div>

内容的提问来源于stack exchange,提问作者staticvoidliam7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 08:39:00