码字不易,有帮助的同学希望能关注一下我的微信公众号:Code程序人生,感谢!代码自用自取。
WebSocket也是前端非常重要的技术栈。
现在各种网站、App、小程序都伴有即时通信的功能。WebSocket的主要应用就是即时通信。
WebSocket的介绍在网上非常非常多,也非常详细,我就不做过多介绍了。
WebSocket的出现解决了远古时期http轮询的”丑陋“。
我这期视频使用原生JavaScript+nodejs实现一个最基本的聊天室功能。
我先介绍一个目录文件:
前端内容存放在chat文件夹中,一共两个页面,entry.html和index.html,后端内容存放在server文件夹中,主要逻辑写在index.js中。
前端部分:
entry.html内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="username" placeholder="请输入用户名"/>
<button id="enter">进入聊天室</button>
<script>
;((doc,storage,location) => {
const oUsername = doc.querySelector('#username');
const oEnterBtn = doc.querySelector('#enter');
const init = () => {
bindEvent();
}
function bindEvent(){
oEnterBtn.addEventListener('click',handleEnterBtnClick,false);
}
function handleEnterBtnClick(){
const username = oUsername.value.trim();
console.log(username);
if(username.length < 6){
alert('用户名不能小于6位');
return;
}
storage.setItem('username',username);
location.href = 'index.html';
}
init();
})(document,localStorage,location);
</script>
</body>
</html>
这个页面主要是做一个登录,做的有点粗糙,没写UI,主要还是为了存放一个localStorage用于下个页面通信。
index.html内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul id="list">
<input type="text" id="message" placeholder="请输入消息" />
<button id="send">发送</button>
</ul>
<script>
const oList = document.querySelector('#list');
const oMessage = document.querySelector('#message');
const oSendBtn = document.querySelector('#send');
let username = '';
const ws = new WebSocket('ws:localhost:8000');
oSendBtn.addEventListener('click',handleSendBtnClick,false);
ws.addEventListener('open',handleOpen,false);
ws.addEventListener('close',handleClose,false);
ws.addEventListener('error',handleError,false);
ws.addEventListener('message',handleMessage,false);
function handleSendBtnClick(){
console.log('send message');
const msg = oMessage.value;
if(!msg.trim().length){
return;
}
ws.send(JSON.stringify({
user:username,
dateTime:new Date().getTime(),
message:msg
}))
oMessage.value = '';
}
function handleOpen(){
console.log('WebSocket open');
username = localStorage.getItem('username');
if(!username){
location.href = 'entry.html';
return;
}
}
function handleClose(){
console.log('WebSocket close');
}
function handleError(){
console.log('WebSocket error');
}
function handleMessage(e){
console.log('WebSocket message');
console.log(e);
const msgData = JSON.parse(e.data);
oList.appendChild(createMsg(msgData));
}
function createMsg(data){
const {user,dateTime,message} = data;
const oItem = document.createElement('li');
oItem.innerHTML = `
<p>
<span>${user}</span>
<i>${new Date(dateTime)}</i>
</p>
<p>消息:${message}</p>
`
return oItem;
}
</script>
</body>
</html>
这个页面是聊天室的内容,伴随了很多dom操作,可能有点乱,我也没有分模块,全写在一起了,方便复制粘贴。
前端部分其实主要就是实例化了一个WebSocket对象,无论是前端还是后端,WebSocket都是一个以事件驱动的方式存在。
前端主要事件是open、close、error、message。
open、close、error的功能就和名字一样,不做过多解释。
主要是message事件,它主要是接收来自后端推送过来的信息。
后端部分
后端在编写之前要先安装ws模块,打开控制台输入
npm i ws -s
index.js
const ws = require('ws');
;((ws)=>{
const server = new ws.Server({port:8000});
const init = () => {
bindEvent();
}
function bindEvent() {
server.on('open',handleOpen);
server.on('close',handleClose);
server.on('error',handleError);
server.on('connection',handleConnection);
}
function handleOpen(){
console.log('WebSocket open');
}
function handleClose(){
console.log('WebSocket close');
}
function handleError(){
console.log('WebSocket error');
}
function handleConnection(ws){
console.log('WebSocket connection');
ws.on('message',handleMessage);
}
function handleMessage(msg){
console.log('WebSocket message');
console.log(msg);
server.clients.forEach(function(c){
c.send(msg);
})
}
init();
})(ws);
后端使用nodejs,也是采用事件驱动的方式执行。
主要事件有:open、close、error、message、connection
前三个事件还是形如其名。
message事件存放于connection事件的参数里的,所以要在connection中绑定message事件。
connection就是代表通信是否连接成功的事件。
message的参数就是前端传过来的信息。
然后要做的就是把接收到的前端信息分发聊天室所有的人。
在代码的最顶部,我们实例化了一个ws模块的Server对象。
Server对象里有一个clients属性,所有登录在聊天室的人都挂载在这个clients属性上。
所以我们只需要forEach循环把接收到的前端信息分发给每一个人即可。
其实到现在为止我们就完成了一个最基本的基于WebSocket技术的原生JavaScript实现的聊天室。
我分别打开了一个chrome浏览器和uc浏览器。
我们看一下效果:
没有任何问题,一个最基本的聊天室的内容已经搭建完成。
如果你想商用,或者参加一些比赛,可以美化一下UI,把一些细节操作优化一下。
可以直接复制文章中的代码,粘贴使用,按照操作来,不会有任何问题。
如果想要源代码文件,关注我的公众号回复聊天室即可。