《Nodejs实战》笔记五:用Express实现留言版功能

35次阅读

共计 3845 个字符,预计需要花费 10 分钟才能阅读完成。

3. Express
Express 是在 connect 基础上搭建的, 先安装 express 的脚手架
npm install -g express-generator
使用 ejs 模板引擎
express -e express-project
3.1 留言版项目规划
功能需求

用户可以注册,登录,退出
用户可以发消息
访问者可以分页浏览条目
有一个简单的 REST API

3.2 渲染视图
Express 几乎支持所有的模板引擎,本项目使用 ejs
Express 有两种渲染视图的方法:

app.render() 在程序层使用
res.render() 在请求或者响应层使用

本项目只会使用 res.render()
3.2.1 了解渲染机制
主要介绍三方面

调整视图的查找
配置默认的模板引擎
启用视图缓存,减少文件 I /O

首先是设置 views,给程序指明渲染视图的路径
app.set(‘views’, __dirname + ‘/views’)
ps: __dirname 表示当前文件的目录
然后指定渲染引擎
app.set(‘view engine’, ‘ejs’);
视图缓存视图缓存 view cache 是默认开启的,如果不开视图缓存,每次渲染
rers.render(‘user’, {name: ‘zmj’})
都会从硬盘中读取 html
如果开启的,读取了一次 html 后,会缓存好,下次再读取的时候直接读取缓存,而不用再去磁盘上读了
3.2.2 将数据传给视图

res.render()
res.locals
app.locals

3.3 express 路由入门
这一节要做留言版的两个功能

用特定路由的中间件校验用户提交的内容
实现特定路由的校验

为了实现校验,给这个程序加上消息提交的功能(用户不提交消息,你咋校验 =。=)
3.3.1 消息提交功能
消息提交功能要完成以下几点

创建消息模型
添加与消息相关的路由
创建消息表单
添加业务逻辑

3.3.2 创建消息模型
表示没有接触过 redis,=。=,硬着头皮来吧。
这里使用到了 redis,安装指南去 github 上下 win10 版本 https://github.com/MicrosoftA… 下载 msi 的
省事,会自动帮你配好服务和环境在 cmd 中测试一下
redis-cli.exe -h 127.0.0.1 -p 6379
设置键值对 set myKey abc
取出键值对 get myKey
这里我们安装好了 redis 服务器后,再去项目里安装 redis 模块
npm install –save redis
redis 的文档 readme 中文命令手册命令官网的 api api
redis 支持很多数据结构,基本常见的都支持这里使用到了列表
创建 models/entry.js
const redis = require(‘redis’)
const db = redis.createClient()

class Entry {
static getRange(from, to, cb) {
db.lrange(‘entries’, from, to, (err, items) => {
if (err) return cb(err)
let entries = []
items.forEach((item) => {
entries.push(JSON.parse(item))
})
cb(null, entries)
})
}

constructor(obj) {
// obj = {a: 1, b: 2, c: 3}
// this[a] = 1, this[b] = 2, this = 3
for (let key in obj) {
this[key] = obj[key]
}
}

save(cb) {
// 将消息转化为字符串,保存到 Redis 列表中
const entryJSON = JSON.stringify(this)
db.lpush(‘entries’, entryJSON, (err) => {
if (err) return cb(err)
cb()
})
}
}

module.exports = Entry
lpush 是 redis 像列表中插入数据的方法,第一个参数是键名,第二个是值,第三个是回调
lrange 是查询数据的方法,第一个参数是键名,第二和第三个是起始位置和结束位置,第四个是回调
3.3.3 添加与消息相关的路由
创建模板文件 post.ejs
<form action=”/post” method=”post”>
<p>
<input type=”text” name=”entry[title]” placeholder=”Title” />
</p>
<p>
<input type=”text” name=”entry[body]” placeholder=”Body” />
</p>
<p>
<input type=”submit” value=”Post”>
</p>
</form>
然后建立路由
app.get(‘/post’, entries.form)
app.post(‘/post’, entries.submit)

/* 下面是 routes/entries 文件 */
// GET ‘/post’
exports.form = (req, res, next) => {
res.render(‘post’, { title: ‘post’});
}

// POST ‘/post’
exports.submit = (req, res, next) => {
console.log(req.body.entry)
res.redirect(‘/’)
// res.render(‘post’, { title: ‘post’});
}
还要注意的地方,得打开 bodyParse 解析
app.use(express.urlencoded({ extended: true}));
将消息存入数据库中
exports.submit = (req, res, next) => {
const data = req.body.entry
const entry = new Entry({
username: ‘zmj’,
title: data.title,
body: data.body
})
entry.save((err) => {
if (err) return next(err)
res.redirect(‘/’)
})
}
显示所有消息
// GET ‘/list’
exports.list = (req, res, next) => {
Entry.getRange(0, -1, (err, entries) => {
console.log(entries)
res.render(‘entries’, {
title: ‘msg list’,
entries: entries
})
})
}
3.3.4 校验表单
说起校验表单,你可能第一种想的方式是在这里面完成
// POST ‘/post’
exports.submit = (req, res, next) => {
const data = req.body.entry
const entry = new Entry({
username: ‘zmj’,
title: data.title,
body: data.body
})
entry.save((err) => {
if (err) return next(err)
res.redirect(‘/’)
})
}
这种方式扩展性不好,我们使用特定的中间件来实现校验, 我们创建一个中间件 middleware/validate.js
const parseField = (field) => {
// 将 entry[filed] 解析为 [‘entry’, ‘filed’]
return field.split(/\[|\]/g).filter((s) => s)
}

const getField = (req, field) => {
// 这个骚操作,我醉了!首先 val = req.body,然后 val = val[entry], 然后 val = entry.filed
let val = req.body
field.forEach((prop) => {
val = val[prop]
})
return val
}

exports.required = (field) => {
field = parseField(field)
return (req, res, next) => {
if (getField(req, field)) {
next()
} else {
res.render(‘error,你必须输入标题 ’)
res.redirect(‘back’)
}
}
}

exports.lengthAbove = (field, len) => {
field = parseField(field)
return (req, res, next) => {
if (getField(req, field).length > len) {
next()
} else {
res.render(`error,你内容必须超过 ${len} 个长度 `)
res.redirect(‘back’)
}
}
}
这段代码理解起来有难度,但这很方便我们使用中间件,以及添加各种验证方式
使用验证表单的中间件
app.post(‘/post’, validate.required(‘entry[title]’), validate.lengthAbove(‘entry[body]’, 5), entries.submit)
我们只需要,将表单字段传过来即可验证,是不是很方便,扩展性也相当好!
该节总结
这一段实现了留言版的功能,使用 redis 当数据库
可以留言,对留言进行了简单的校验
这一节做了三个路由

GET /post: 显示消息表单
POST /post: 提交消息表单
GET /list: 获取消息列表

总言之,学到了不少东西。很多东西都是书上没写需要自己去手动查资料的,像 express 的一些 api,redis 的使用等等

正文完
 0