如何在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
相关产品推荐
相关产品推荐

