原生node实现简易留言板
原生node实现简易留言板
学习node,实现一个简单的留言板小demo

1. 使用模块
http模块
创建服务
fs模块
操作读取文件
url模块
便于path操作并读取表单提交数据
art-template模块(需npm安装)
服务端渲染
2. 服务端
2.1 服务端代码
var http = require('http')
var fs = require('fs')
var url = require('url')
var template = require('art-template')
var comments = [
{
name:'阿孔',
message: 'Yo~~',
dataTime: '2018-09-27'
},
{
name: '老许',
message: 'Yo~@@@~',
dataTime: '2018-09-27'
}
]
http.createServer(function (req, res) {
var parseObj = url.parse(req.url, true)
var pathname = parseObj.pathname
if (pathname === '/') {
fs.readFile('./views/留言本.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.indexOf('/public/') === 0) {
fs.readFile('.' + pathname, function (err, data) {
if (err) {
return res.end('404 Not Found')
}
res.end(data)
})
} else if (pathname === '/post') {
fs.readFile('./views/post.html', function (err, data) {
if (err) {
return res.end('404 Not Found')
}
res.end(data)
})
} else if (pathname === '/pinglun') {
// 追加到数组
var comment = parseObj.query
comment.dataTime = '2018-10-01'
comments.unshift(comment)
// 跳转首页
// 如何通过服务器让客户端重定向
// 1. 状态码设置为 302 临时重定向 statusCode
// 2. 在响应头中通过 location 告诉客户端去哪重定向
res.statusCode = 302
res.setHeader('Location', '/')
res.end()
} else {
fs.readFile('./views/404.html', function(err, data) {
res.end(data)
})
}
}).listen(3000, function () {
console.log('http://localhost:3000')
})
2.2 页面渲染
使用了 第三方 的渲染模板工具
art-template,在请求 / 主页时,在服务端将页面中的数据渲染出来 数据来自comments数组
if (pathname === '/') {
fs.readFile('./views/留言本.html', function (err, data) {
if (err) {
return res.end('404 Not Found')
}
var htmlStr = template.render(data.toString(), {
comments: comments
})
res.end(htmlStr)
})
}
2.3 评论提交
评论提交的实现,在post提交页面中 form表单的行为action指定
/pinglun,随后在服务端的app.js中处理/pinglun路径请求逻辑
else if (pathname === '/pinglun') {
// 追加到数组
var comment = parseObj.query
comment.dataTime = '2018-10-01'
comments.unshift(comment)
// 跳转首页
// 如何通过服务器让客户端重定向
// 1. 状态码设置为 302 临时重定向 statusCode
// 2. 在响应头中通过 location 告诉客户端去哪重定向
res.statusCode = 302
res.setHeader('Location', '/')
res.end()
}
其中,有几点需要注意
parseObj
parseObj是通过url模块解析每次请求的路径得到的
var parseObj = url.parse(req.url, true)url中的parse方法可以将url解析为一段一段的数据
例如,我们在 node 中 执行下面代码
var parseObj = url.parse('http://localhost:3000/pinglun?name=aaa&message=bbbbbbb', true)
console.log(parseObj) Url {
protocol: 'http:',
slashes: true,
auth: null,
host: 'localhost:3000',
port: '3000',
hostname: 'localhost',
hash: null,
search: '?name=aaa&message=bbbbbbb',
query: { name: 'aaa', message: 'bbbbbbb' },
pathname: '/pinglun',
path: '/pinglun?name=aaa&message=bbbbbbb',
href: 'http://localhost:3000/pinglun?name=aaa&message=bbbbbbb' }
可以看到,url的方法直接将url解析成一个对象,里面包含着很多我们能方便使用的属性,入其中的query,这里面就包含着我们提交的数据信息,url.parse方法的第二个参数默认为 false ,若默认false的话,query就不是一个对象,而是一个字符串,设置为true后就会自动帮我们解析成一个对象,方便我们使用。
我们评论的追加就是取得这个parseObj.query对象中的数据
var comment = parseObj.query
comment.dataTime = '2018-10-01'
comments.unshift(comment)
最后在使用unshift数组方法追加到最前面,这样我们的评论功能就能实现了。
2.4 服务端重定向
我们在追加我们的评论后,需要跳转到我们的 / 主页,这是我们的 comments已经追加新数据, 在渲染的时候,自然就能将我们的新数据展现到我们的页面中。
关于重定向,此次有两部操作
res.statusCode = 302
res.setHeader('Location', '/')
第一步设置res请求的状态码,状态302 是临时重定向的状态码,
而后我们设置响应头的Location设置为 主页
访问别的页面:response.setStatus(302); response.setHeader("location","url");
2.5 代码杂点笔记
模块加载在node中是同步的,通常把当前模块所有的依赖项都声明再文件模块最上面
为了让目录结构保持统一清晰,所以我们约定,把所有的 HTML 文件都放到 views(视图) 目录中,把所有的静态资源都存放在 public 目录中
浏览器收到 HTML 响应内容之后,就要开始从上到下依次解析,
当在解析的过程中,如果发现:
- link
- script
- img
- iframe
- video
- audio
等带有 src 或者 href(link) 属性标签(具有外链的资源)的时候,浏览器会自动对这些资源发起新的请求。
在这中服务端中,请求文件路径不要再去写相对路径了,因为这个时候所有的资源都是通过url来获取的,我们服务器开放了/public/目录,这里的静态资源的请求,如bootstrap.css都写为:
<link rel="stylesheet" href="/public/lib/bootstrap/dist/css/bootstrap.css">浏览器在真正发请求的时候会最终把http://localhost:3000 拼在前面
3. 客户端
3.1 客户端代码
<body>
<div class="header container">
<div class="page-header">
<h1>留言板 <small>--- a small demo of node</small></h1>
<a class="btn btn-success" href="/post">发表留言</a>
<hr>
</div>
</div>
<div class="comments container">
<ul class="list-group">
{{each comments}}
<li class="list-group-item">{{$value.name}}说: {{$value.message}}<span class="float-right">{{$value.dataTime}}</span></li>
{{/each}}
</ul>
</div>
</body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="/public/lib/bootstrap/dist/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">
<!--
以前表单是如何提交的?
表单中需要提交的表单控件元素必须具有 name 属性
表单提交分为:
1. 默认的提交行为
2. 表单异步提交
action 就是表单提交的地址,说白了就是请求的 url 地址
method 请求方法
get
post
-->
<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>
所有的代码都在github仓库github代码
原生node实现简易留言板的更多相关文章
- JSP简易留言板
写在前面 在上篇博文JSP内置对象中介绍JSP的9个内置对象的含义和常用方法,但都是比较理论的知识.今天为大家带来一个小应用,用application制作的简易留言板. 包括三个功能模块:留言提交.留 ...
- DOM操作相关案例 模态对话框,简易留言板,js模拟选择器hover,tab选项卡,购物车案例
1.模态框案例 需求: 打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框 代码如下: <!DOCTYPE html> <h ...
- Flask学习之旅--简易留言板
一.写在前面 正所谓“纸上得来终觉浅,方知此事要躬行”,在看文档和视频之余,我觉得还是要动手做点什么东西才能更好地学习吧,毕竟有些东西光看文档真的难以理解,于是就试着使用Flask框架做了一个简易留言 ...
- php实现简易留言板效果
首先是Index页面效果图 index.php <?php header('content-type:text/html;charset=utf-8'); date_default_timezo ...
- 原生JS实现简单留言板功能
原生JS实现简单留言板功能,实现技术:css flex,原生JS. 因为主要是为了练手js,所以其中布局上的一些细节并未做处理. <!DOCTYPE html> <html lang ...
- 微信小程序实现简易留言板
微信小程序现在很火,于是也就玩玩,做了一个简易的留言板,让大家看看,你们会说no picture you say a j8 a,好吧先上图. 样子就是的,功能一目了然,下面我们就贴实现的代码,首先是H ...
- vue实现简易留言板
首先引入vue.js <script src="vue.js"></script> 布局 <div id="div"> &l ...
- js简易留言板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...
- js 实现简易留言板功能
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
随机推荐
- isap算法模板poj 1273gap+弧优化 最大流
几个比较好的博客 http://www.renfei.org/blog/isap.html http://kenby.iteye.com/blog/945454 http://blog.csdn.ne ...
- Docker installation in sles SP2
Please refer to official site for installation details : https://docs.docker.com/install/linux/doc ...
- 安装GCC for Red Hat Enterprise Linux Server release 6(64位)
http://www.cnblogs.com/emanlee/archive/2012/08/11/2633895.html
- 【cl】java变量
知识点一: 变量:有声明,有初始化! 变量作用域:变量在声明的地方开始,到块结束(其中一对{}叫块) 变量不能重复声明(声明=定义):在同一个作用域中不能重复声明变量! 在作用域中如果已经有变量了,就 ...
- 用python阐释工作量证明(proof of work)
了解比特币的都知道挖矿非常耗电,这是由于比特币用到了工作量证明. 工作量证明是指系统为达到某目标而设置的工作度量方法.一開始是用在网络攻防上,大大提高攻击者的计算量,攻击成本也就上去了. 工作量证明须 ...
- C++派生类中如何初始化基类对象(五段代码)
今天收到盛大的面试,问我一个问题,关于派生类中如何初始化基类对象,我在想派生类对于构造函数不都是先构造基类对象,然后在构造子类对象,但是如果我们在成员初始化列表先初始化派生类的私有成员,在函数内去调用 ...
- C C++每个头文件的功能说
C/C++每个头文件的功能说明 传统 C++ #include <assert.h> //设定插入点 #include <ctype.h> //字符处理 #include &l ...
- 在ubuntu中安装与配置zsh与oh-my-zsh
先补充点东西 1.ubuntu中默认安装了那些shell jiang@Linux:~$ cat /etc/shells # /etc/shells: valid login shells/bin/sh ...
- hdoj--1045--Fire Net(二分图)
Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- NEU操作系统实验课4——线程同步
实验要求: 创建两个线程按数字顺序打印10以下自然数,其中一个线程打印1-3及8-10:另一个线程打印4-6.要求使用线程同步机制实现上述打印顺序. 看网上的资料学习了两种写法 C++11的,使用了s ...