koa 是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。
Koa 融合了ES6的一些新特性,使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。
koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。
功能
- 自动分配聊天室
- 提示添加昵称
- 防止xss攻击
- 加入、离开时发送系统消息
- 为每个用户随机分配颜色
- 当前用户的消息显示在右侧,其它用户消息显示在左则
环境
安装node4.0以上版本,以确保fvES6的新特性
新建文件koa_chat
npm init
创建 package.json
创建koa_chat项目目录如下:.
├── public
│ ├── index.css
│ ├── index.js
│ └── index.html
│ └── socket.io.js
├── package.json
├── server_index.js
├── README.md
安装依赖npm install koa.io --save
npm install koa-static-cache --save
这样koa的环境就搭建好了,编辑文件server_index.js
var koa = require('koa.io');
var staticCache = require('koa-static-cache');
var app = koa();
app.use(function* (){
this.body = 'Hello World';
});
app.listen(3000);
保存,使用命令 node server_index
预览
前端逻辑
页面结构
public/index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Socket.IO Chat Example</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h2 class="page-header"> Koa.io 聊天室 v1.0.0</h2>
<div class='container'>
<ul class="pages">
<!-- chat list -->
<li class="chat-page" id="chatPage">
<div class="chatArea">
<ul class="messages" id="msgBox">
<li class="msg-item msg-left">
<dl class="box">
<dt class="name">jack</dt>
<dd class="con">hello!</dd>
</dl>
</li>
<li class="msg-item msg-right">
<dl class="box">
<dt class="name">mary</dt>
<dd class="con">Nice to meet you!</dd>
</dl>
</li>
<li class="msg-sys"><p class="con">新用户加入 <time>22:29:22</time></p></li>
</ul>
</div>
<input id="msgIpt" class="inputMessage" placeholder="说点儿什么吧..."/>
<div class="user-list">
<p>当前在线:<b id="userNum"></b>人</p>
<ul id="userList">
<li>暂无在线人员!</li>
</ul>
</div>
</li>
<!-- login -->
<li class="login-page" id="loginPage">
<div class="form">
<div class="form-group">
<input class="usernameInput" type="text" maxlength="14" id="usernameInput" />
<h3 class="form-label">Give me your name!</h3>
</div>
</div>
</li>
</ul>
<input type="hidden" id="currUser">
</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="/socket.io.js"></script>
<script src="/index.js"></script>
</body>
</html>
效果预览
后端逻辑
脚本编写
server_index.js
var koa = require('koa.io');
var staticCache = require('koa-static-cache');
var path = require('path');
var fs = require('fs');
var app = koa();
var port = process.env.PORT || 3000;
var userList = [];
var userModel = {
hasUser:function(uName){
return userList.indexOf(uName)>0;
},
delUser:function(uName){
var i = userList.indexOf(uName);
if(i>0) userList.splice(i,1);
return userList;
},
addUser:function(uName){
userList.push(uName);
}
}
// set staict path
app.use(staticCache(path.join(__dirname, 'public')));
// 输出主页面
app.use(function *(){
this.body = fs.createReadStream(path.join(__dirname, 'public/index.html'));
this.type = 'html';
});
// 启动服务端口,并打印日志
app.listen(port, function(){
console.log('Server start at port %d', port);
})
// 监听用户连接和断开
app.io.use(function* (next){
console.log('新用户已连接!');
this.emit('welcome', '欢迎来到 Koa.io 聊天室!');
yield* next;
if(this.uName){
userModel.delUser(this.uName);
console.log('用户 '+this.uName+' 退出');
this.broadcast.emit('user_left', this.uName, userList);
}
});
// 监听add_user动作 并处理请求
app.io.route('add_user', function* (next, uName, color){
if(userModel.hasUser(uName)){
console.log('用户名重复!');
return this.emit('add_user_err', '昵称已被占用了')
}
console.log('新用户 '+uName+' 加入');
this.uName = uName;
this.color = color;
userModel.addUser(uName);
// 触发前端的展示用户的回调
this.emit('show_users', userList);
// 广播 新用户加入
this.broadcast.emit('user_join', uName, userList);
})
// 监听新消息,并广播出去
app.io.route('new_msg', function* (next, msg){
console.log(this.uName + '发送消息:'+ msg);
// 广播 用户消息
this.broadcast.emit('user_say', msg, this.uName, this.color);
// 触发当前用户展示消息的回调
this.emit('say_done', msg, this.uName, this.color);
});