使用Node.js搭建简易聊天室
功能概述:
可以模拟聊天室,每个人自定义用户名和消息,在“首页”发表“评论”。
但是,并没有实现数据持久化(没用数据库),只是一个简单的案例
使用到:Bootstrap、art-template模板引擎。
目录
1.核心源码 app.js:
var http = require('http');
var fs = require('fs');
var url = require('url');
var template = require('art-template');
//模拟5条数据
var comments = [
{
name: 'Node',
message: 'Hello Node.js',
dateTime: '2018年08月02日 09:01:50'
},
{
name: 'Node2',
message: 'Hello Node.js',
dateTime: '2018年08月02日 09:01:50'
},
{
name: 'Node3',
message: 'Hello Node.js',
dateTime: '2018年08月02日 09:01:50'
},
{
name: 'Node4',
message: 'Hello Node.js',
dateTime: '2018年08月02日 09:01:50'
},
{
name: 'Node5',
message: 'Hello Node.js',
dateTime: '2018年08月02日 09:01:50'
}
];
// 对于这种表单提交的请求路径,由于其中具有用户动态填写的内容
// 所以你不可能通过去判断完整的 url 路径来处理这个请求
http
.createServer(function (req, res) {
// 使用 url.parse 方法将路径解析为一个方便操作的对象,
// 第二个参数为 true 表示直接将查询字符串转为一个对象(通过 query 属性来访问)
var parseObj = url.parse(req.url, true);
// 单独获取不包含查询字符串的路径部分(该路径不包含 ? 之后的内容)
// 例如 /pinglun?name=Node&message=helloNode
//调用下面的方法,返回 /pinglun
var pathname = parseObj.pathname;
if (pathname === '/') {
fs.readFile('./views/index.html', function (err, data) {
if (err) {
return res.end('404 Not Found.')
}
//渲染数据
var htmlStr = template.render(data.toString(), {
comments: comments
});
res.end(htmlStr)
})
} else if (pathname === '/post') {
// 其它的都处理成 404 找不到
fs.readFile('./views/post.html', function (err, data) {
if (err) {
return res.end('404 Not Found.');
}
res.end(data);
})
} else if (pathname.indexOf('/public/') === 0) {
// /public/js/main.js
// /public/lib/jquery.js
// 统一处理:
// 如果请求路径是以 /public/ 开头的,则我认为你要获取 public 中的某个资源
// 所以我们就直接可以把请求路径当作文件路径来直接进行读取
fs.readFile('.' + pathname, function (err, data) {
if (err) {
return res.end('404 Not Found.');
}
res.end(data)
})
} else if (pathname === '/pinglun') {
// 注意:这个时候无论 /pinglun?xxx 之后是什么,我都不用担心了,因为我的 pathname 是不包含 ? 之后的那个路径
// 我们已经使用 url 模块的 parse 方法把请求路径中的查询字符串给解析成一个对象了
//1. 获取表单提交的数据 parseObj.query
var comment = parseObj.query;
//2. 将当前时间日期添加到数据对象中
comment.dateTime = getNowTime();
//3.存储到数组中,unshift为存在数组头
comments.unshift(comment);
//服务端这个时候已经把数据存储好了,接下来就是让用户重新请求 / 首页,就可以看到最新的留言内容了
//4. 让用户重定向跳转到首页 /
//5. 状态码设置为 302 临时重定向
res.statusCode = 302;
//6. 在响应头中通过 Location 告诉客户端往哪儿重定向
res.setHeader('Location', '/');
// 如果客户端发现收到服务器的响应的状态码是 302 就会自动去响应头中找 Location ,然后对该地址发起新的请求
// 所以客户端自动跳转了
//当用户重新请求 / 的时候,我数组中的数据已经发生变化了,所以用户看到的页面也就变了
res.end()
} else {
// 其它的都处理成 404 找不到
fs.readFile('./views/404.html', function (err, data) {
if (err) {
return res.end('404 Not Found.');
}
res.end(data);
})
}
})
.listen(8888, function () {
console.log('running...');
})
//获取当前时间方法
function getNowTime() {
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth()+1;
var day = date.getDate();
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
var myTime = (year+'年'+(month>9?month:'0'+month)
+'月'+(day>9?day:'0'+day)+'日 '
+(hour>9?hour:'0'+hour)+':'
+(minute>9?minute:'0'+minute)
+':'+(second>9?second:'0'+second));
return myTime;
}
2.视图
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>留言本</title>
<link rel="stylesheet" href="/public/css/bootstrap.css">
</head>
<body>
<div class="header container">
<div class="page-header">
<h1>首页
<small>Node聊天室</small>
</h1>
<a class="btn btn-success" href="/post">发表留言</a>
</div>
</div>
<div class="comments container">
<ul class="list-group">
{{each comments}}
<li class="list-group-item">{{ $value.name }}说:{{ $value.message }} <span class="pull-right">{{ $value.dateTime }}</span>
</li>
{{/each}}
</ul>
</div>
</body>
</html>
post.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="/public/css/bootstrap.css">
</head>
<body>
<div class="header container">
<div class="page-header">
<h1><a href="/">首页</a>
<small>发表评论</small>
</h1>
</div>
</div>
<div class="comments container">
<form action="/pinglun" method="get">
<div class="form-group">
<label for="input_name">你的大名</label>
<input type="text" class="form-control" required minlength="2" maxlength="10" id="input_name" name="name"
placeholder="请写入你的姓名">
</div>
<div class="form-group">
<label for="textarea_message">留言内容</label>
<textarea class="form-control" name="message" id="textarea_message" cols="30" rows="10" required
minlength="5" maxlength="20"></textarea>
</div>
<button type="submit" class="btn btn-default">发表</button>
</form>
</div>
</body>
</html>
3.效果图:
首页:
评论页: