NodeJs实现简单聊天室效果
基于NodeJs 利用express框架实现聊天室效果,
主要需要模块如下:express、socket.io、ejs 还需要加载jquery和bootstarp模块(可选)
功能实现:主要实现多人在线实时群聊
鸣谢:模版制作@梦凡
以下是js代码:
//加载express框架 var express = require("express"); //创建应用 var app = express(); //创建服务 var server = require('http').Server(app); //加载socket模块 var io = require('socket.io')(server); //设置静态资源 app.use(express.static("node_modules")); //加载模版 app.set("view engine", "ejs"); //设置模版目录 app.set("views", "./views"); //设置路由 app.get('/', function (req, res) { res.render('index'); res.end(); }); //连接socket服务 io.on("connection", function (socket) { //设置端口 接收并广播消息数据 socket.on('44', function (data) { // console.log(data); //广播消息数据 socket.broadcast.emit('44', data); }) }) //设置监听端口 server.listen(8080);
ejs引擎模版中代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>在线聊天 By:NodeJs</title> <link rel="stylesheet" href="/liaotian/css/style.css"> <link rel="stylesheet" href="https://at.alicdn.com/t/font_1465982_zggqnzvtvm.css"> <script src="/liaotian/js/jquery-1.8.3.min.js"></script> <script src="/socket.io/socket.io.js"></script> </head> <body> <div class="maxbox"> <div class="box"> <div class="gn"> <div class="tx"> <img src="/liaotian/images/tx.jpg" alt="" onselectstart="return false;"> </div> <ul class="tab"> <li><i class="iconfont icon-xiaoxi"></i></li> <li><i class="iconfont icon-duoren"></i></li> <li><i class="iconfont icon-shoucang"></i></li> <li><i class="iconfont icon-wenjian"></i></li> </ul> </div> <div class="lxr"> <div class="top"> <div class="ss"> <div class="fdj"><i class="iconfont icon-fangdajing"></i></div> <input type="text" placeholder="搜索" onselectstart="return false;"> </div> <div id="tj"> <i class="iconfont icon-jia"></i> </div> </div> <div class="lb"> <ul class="lsdh"> <li id="dq"> <div class="lxrtx"> <img src="/liaotian/images/1.jpg" alt=""> </div> <div class="nc"> <span onselectstart="return false;">小骚逼群聊</span> </div> <div class="sclt" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"> <span onselectstart="return false;"></span> </div> <div class="sj"> <span onselectstart="return false;"></span> </div> </li> </ul> </div> </div> <div class="fs"> <div class="fstop"> <div class="mz"> <span onselectstart="return false;" id="nickName">小骚逼群聊</span> </div> </div> <!-- 消息框(将来自己的消息和回复的消息都会出现在这里) --> <div class="lsxx"> </div> <div class="sr"> <div id="srk"> <textarea name="" id="dwb"></textarea> </div> <div class="fsxx"> <button id="ffss" style="cursor:pointer;">发送</button> </div> </div> <div id="bnk" style="display: none;"> <!-- 自己消息(用于后面克隆) --> <div class="zjxx clearfix"> <div class="zjtx"> <div class="picName" style="background: chocolate;"></div> </div> <div class="zjxxk"> <span></span> </div> </div> </div> </div> </div> </div> </body> <script> //获取最后消息时间函数 function getDate(){ var date=new Date; var h=date.getHours(); var m=date.getMinutes(); var sj=h+':'+m; //将时间插入到页面中 $(".sj span").html(sj); } //获取当前时间 getDate(); //清空名字 $(".nc span").html(""); //定义访问者名字 var name=prompt("请输入你的名字"); //连接socket服务 var socket=io.connect("/"); //判断名字不能为空 if(name==""){ //如果为空则再次输入 var name=prompt("请输入你的名字"); } //设置自己的头像 $(".zjtx .picName").html(name.substr(0,1)); //设置自己的名字 $(".nc span").html(name); //绑定发送按钮 $("#ffss").click(function(){ if($("#dwb").val()==""){ alert("请输入内容"); return false; } //将内容输出到消息栏 $("#bnk span").html(fun($("#dwb").val())); //克隆元素 var me=$("#bnk .zjxx").clone(); //将元素插入到消息栏后面 $(".lsxx").append(me); //滚动条跟随 $('.lsxx').scrollTop( $('.lsxx')[0].scrollHeight ); //向群组发送消息请求 socket.emit('44',{name:$(".nc span").html(),data:$("#dwb").val()}); //清空发送框内容 $("#dwb").val(""); }) //绑定键盘事件 $("#dwb").keydown(function(e){ //组合键按下实现换行 if(e.ctrlKey && e.keyCode==13){ $(this).val($(this).val()+'\r\n'); return false; } //实现回车键发送消息 if(e.keyCode==13){ //执行按钮点击事件 $("#ffss").trigger("click"); //清空发送框内容 $(this).val(""); //取消按键默认行为 return false; } }) //接收消息 socket.on('44',function(data){ //更新时间 getDate(); //设置他人头像 var szm=data.name.substr(0,1); //创建一个回复消息盒子以及里面的内容 var hd=$('<div class="dmxx clearfix"><div class="dmtx"><div class="picName">'+szm+'</div></div><div id="nickNames" style="width:120px;height:20px;color: #aaa;font-size:12px;padding-left:50px;">'+data.name+'</div><div class="dmxxk"><span>'+fun(data.data)+'</span></div></div>'); //将最后回复消息同时插入到左边群组下方消息框 $(".sclt").html(fun(data.data)); //将回复消息盒子及内容插入到消息框末尾 $(".lsxx").append(hd); //再次执行滚动条跟随 $('.lsxx').scrollTop( $('.lsxx')[0].scrollHeight ); }) //消息内容正则 过滤 function fun(obj){ //定义一个敏感词数组 var list=['<','>','alert']; list.forEach(function(ele){ var reg=new RegExp(ele,"g"); obj=obj.replace(reg,"*"); }) return obj; } </script> </html>
css布局样式代码
*{ margin:0px; padding:0px; } /* * 解决高度塌陷问题clearfix */ .clearfix:before, .clearfix:after{ content: ""; display: table; clear: both; } .clearfix{ zoom:1; } ul li{ list-style: none; } .maxbox{ background: #ccc; width:100%; height:720px; overflow: hidden; } .box{ width:1000px; height: 600px; background:rgba(0,0,0,0.5); position: relative; top:0px; left:0px; } .gn{ width:75px; height: 100%; background:rgba(0,0,0,0.5); position: absolute; } .tx{ width:43px; height:43px; margin:25px auto 0; } .tx img{ width:100%; } .tab{ width:43px; margin:36px auto 0; } .tab li{ width:43px; height:43px; margin-top:38px; cursor: pointer; } .tab li:first-child{ margin-top:0px; } .tab li i{ font-size: 28px; color:#959595; width:28px; margin:0 auto; display: block; line-height: 43px; } .lxr{ width:313px; height:100%; background: #e2e1e0; position: absolute; left:75px; } .top{ width:100%; height:78px; background: #ebeaea; } .ss{ width:238px; height:31px; border-radius:7px; background: #dbd9d8; position: absolute; top:31px; left:21px; } .ss input{ position: absolute; width:200px; height:31px; top:0px; left:30px; background: none; border: none; outline: none; } .fdj{ width:15px; height:100%; line-height: 31px; margin-left:7px; } .fdj i{ font-size: 15px; color:#6e6d6d; width:15px; margin:0 auto; display: block; line-height: 31px; } #tj{ width:31px; height:31px; border-radius:7px; background: #dbd9d8; position: absolute; top:31px; right:16px; cursor: pointer; } #tj i{ font-size:14px; color: #626262;; width:14px; display: block; margin:0 auto; line-height: 31px; } .lb{ width:100%; height: 522px; overflow: auto; position: relative; } .lsdh li{ width:100%; height:80px; position: relative; cursor: pointer; background: #eae8e7; } .lxrtx{ width:50px; height:50px; background: #888; position: absolute; left:15px; top:15px; } .lxrtx img{ width:100%; } .nc{ width:150px; height:25px; position: absolute; left:75px; top:20px; } .nc span{ font-size: 16px; color:#333; } .sclt{ width:150px; height:18px; position: absolute; left:75px; top:40px; } .sclt span{ font-size:12px; color:#666; } #dq{ background: #c3c3c3; } .sj{ width:30px; height:20px; position: absolute; right:10px; top:15px; } .sj span{ font-size: 12px; color:#888; } .fs{ width:612px; height: 100%; background: #f5f5f5; position: absolute; right:0px; } /*滚动条样式*/ .lb::-webkit-scrollbar {/*滚动条整体样式*/ width: 4px; /*高宽分别对应横竖滚动条的尺寸*/ height: 4px; } .lb::-webkit-scrollbar-thumb {/*滚动条里面小方块*/ border-radius: 5px; -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); background: rgba(0,0,0,0.2); } .lb::-webkit-scrollbar-track {/*滚动条里面轨道*/ -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); border-radius: 0; background: rgba(0,0,0,0.1); } .fstop{ width:100%; height:78px; background: #f5f5f5; border-bottom: 1px solid #e7e7e7; } .mz{ width: 130px; height:30px; position: relative; top:35px; left:38px; } .mz span{ font-size:18px; font-weight: 500; color:#333; } .sr{ width:100%; height: 141px; background: #fff; position: absolute; bottom:0px; border-top:1px solid #ececec; } #srk{ width:572px; height:80px; position: absolute; top:50px; left:50%; margin-left:-286px; } #dwb{ width:572px; height:80px; font-size:18px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; overflow: auto; resize:none; background: none; border:none; outline: none; } .fsxx{ position: absolute; right:20px; bottom: 20px; } .fsxx button{ width:85px; height:33px; color:#fff; border: none; outline: none; background: #09bb07; } .zj-lsxx{ width:100%; height:339px; background:#f5f5f5; overflow: auto; } .zjxx{ width:541px; margin: 20px auto 30px; } .zjtx{ width:43px; height:43px; float:right; } .zjtx img{ width:100%; } .lsxx{ width:100%; height:339px; background:#f5f5f5; overflow: auto; } .zjxx{ width:541px; margin: 20px auto 30px; } .zjtx{ width:43px; height:43px; float:right; } .zjtx img{ width:100%; } .dmxx{ width:541px; margin: 20px auto 30px; } .dmtx{ width:43px; height:43px; float:left; } .dmtx img{ width:100%; } .zjxxk{ max-width: 300px; background: #9eea6a; float:right; margin-right:10px; border-radius: 5px; padding: 10px; } .zjxxk span{ white-space:normal; word-break:break-all; overflow:hidden; line-height: 20px; font-size:14px; color:#333; text-align: left; } .dmxxk{ max-width: 300px; background: #fff; float:left; margin-left:10px; border-radius: 2px; padding: 6px; } .dmxxk span{ white-space:normal; word-break:break-all; overflow:hidden; line-height: 20px; font-size:14px; color:#333; text-align: left; } .lsxx::-webkit-scrollbar {/*滚动条整体样式*/ width: 4px; /*高宽分别对应横竖滚动条的尺寸*/ height: 4px; } .lsxx::-webkit-scrollbar-thumb {/*滚动条里面小方块*/ border-radius: 5px; -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); background: rgba(0,0,0,0.2); } .lsxx::-webkit-scrollbar-track {/*滚动条里面轨道*/ -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); border-radius: 0; background: rgba(0,0,0,0.1); } .picName { width: 40; height:40px; border-radius:2px; background:#47A1F8; color:#fff; font-weight:bold; line-height:40px; text-align:center; font-size:23px; }
评论