作为唯一一个与 JavaScript 相关的服务器编程语言,node.js 在web前端工程师中广受欢迎。它的语法接近 JavaScript,但它的运行环境却在服务端,node.js 可以做很多事,比如,最简单的可以做一个博客系统,也可以用它开发一个多人在线的游戏,还可以针对本地文件做一个自动化构建工具,以及数据爬虫、聊天室等各种应用。另外,它还拥有全球最大的开源生态系统(NPM)。

在我看来,要熟悉和了解node.js,没有什么比搭建一个博客系统更快、更有效了。

因此,本篇文章的目标很明确!用node.js搭建一个极简的博客系统。

为了更直观说明我们将要完成的事,首先来看下博客截图,分别是 博客首页 和 博客更新页:

从以上博客截图,这是一个非常简洁的博客发布系统。主要有两个页面(首页和更新页),包含了发布博客、删除博客、更新博客和读取博客四个功能(即数据的增删改查)。

要搭建这样一个博客,毫无疑问,首先需要一门服务器语言,这里当然指的是node.js。但因为node.js书写起来比较原生,因此我们采用最流行、最成熟、最广泛的node.js框架-express。其次,要在后台记录数据,则需要数据库来支撑,在这里我们选用node.js的黄金搭档数据库-mongodb。

了解完博客的大体情况后,我们先熟悉需要用到的几项技术。

一、express

要使用express,首先你得安装node.js,前往官网 https://nodejs.org/en/download/ 找到对应的系统和版本安装即可,这里不赘诉了。

而说到express,借用官网的一句话:

“Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用。”

简单来说,express封装了很多原生的node.js操作,通过安装后的express,可以调用路由、模板引擎、中间件等相关方法,从而很方便的写node.js。

假设我们的项目在G盘,项目名称为 blog:,接着,我们来完成express安装、快速生成项目、依赖包安装,express项目启动等步骤。

1.1 使用命令行全局安装express:

> npm install express-generator -g

见截图:

安装完成后,你可以通过以下命令来检测express的版本号:

> express -V

1.2 快速生成项目

express给我们提供了一个命令,用于快速创建一个应用的文件以及相关目录。假设项目名称为 blog,则可以:

> express blog

见截图:

1.3 进入项目并安装依赖

创建完成项目后,我们运行命令行进入项目目录,并且安装express需要的依赖包:

> cd blog && npm install

见截图:

1.4 启动express

准备工作基本完成,接着我们通过以下命令启动express:

> npm start

见截图:

最后在浏览器中,打开 http://localhost:3000/,即可看到以下界面:

虽然我们成功搭建了express,但它启动后的默认界面与我们要的博客系统大相径庭,之后,我们会根据博客系统界面对express生成的默认文件进行相应修改和调整。

如果你想更多的了解它,也可以访问它的中文官网:http://www.expressjs.com.cn/

说完node.js的web框架express,接下来,我们来讲讲数据库。

二、mongodb

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

关系型数据库和非关系型数据库的结构对比如下:

数据库类型 一级结构 二级结构 三级结构 四级结构
关系型数据库 一条记录 字段
非关系型数据库 集合 文档

从表中可以知道,mongodb数据库是由集合组成,而集合是由文档组成,而文档是由一组组键值对组成。也就是说,mongodb中最小的单位为文档。

如果要细说mongodb,恐怕一本书的内容也很难将它讲完。因为本文只是做一个极简的博客系统,因此在这里只会描述mongodb的必要操作。

2.1 数据库相关配置

2.1.1 下载与安装

要使用mongodb,首先要安装它,安装它的方法与node.js.类似:

下载地址:https://www.mongodb.org/downloads#production

将压缩包解压后,然后安装到某个目录下,假设安装的路径为 D:\SEVER-SOFTWARE\SEVER\Mongodb

2.1.2 配置环境变量

通过配置环境变量,这样我们就可以在命令行的任何地方运行mongodb,而无需进入到mongodb中bin的目录。

配置的方法如下:

计算机->属性->高级系统设置->环境变量->底部变量中找到 path->编辑->在输入框最后加入分号->分号后面加 mongodb中bin的目录(D:\SEVER-SOFTWARE\SEVER\Mongodb\bin)

2.1.3 设置数据存放目录

每个项目都有保存数据的目录,我们之前创建的 blog 项目也不例外。我们在 blog 目录下,先创建一个 data 的文件夹,用于存放blog下的所有数据。

在任意目录打开命令行窗口,执行以下命令:

> mongod.exe --dbpath G:\blog\data

运行完后,当看到命令窗口中出现类似 waiting for connections on port 27017 字符时,说明设置数据存放目录成功。并且此时,我们在 G:\blog\data 目录中会看到有 journal 和 mongod.lock 等文件。

2.1.4 启动mongodb

假设我们是第一次设置数据存放的目录,那么通过上述“设置数据存放目录”的步骤,你已经启动了mongodb。

但倘若我们已经设置了数据存放目录,则只需要在任意目录(一般直接 Win+R,然后输入 cmd 即可),通过以下相同的命令来启动mongodb:

> mongod.exe --dbpath G:\blog\data

2.2 数据的操作

要访问 blog 里数据,需要在数据存放目录(即 G:\blog\data)打开命令行。

注意,数据库的操作前,需要先启动 mongodb(前面已介绍)。

也就是说,操作数据库时,我们总共打开了两个命令面板。一个是启动 mongodb 的,另外一个是操作当前项目数据库的。而我们需要关注和处理的,只是操作数据库的命令面板。

对于操作数据库的命名面板,运行如下命令,连接数据库:

> mongo

此时,在命令行中打印出了mongodb的版本号,并且默认连接的是 test 数据库。

接下来,我们来简单的说说数据库、集合、文档的相关操作。

2.2.1 数据库操作

要查看本地有哪些数据库,只需要执行以下命令:

> show dbs

若你要查看当前所操作的数据库,则需通过以下命令:

> db

当需要新建一个数据库,使用 use DATABASE_NAME 命令,此时本地会自动创建一个名为 DATABASE_NAME 的数据库,因此你无需特意创建数据库。以下是创建一个名为 blog 的数据库:

> use blog

当你再次使用 show dbs 查看本地数据库时,会发现我们刚才创建的 blog 数据库并没有列出来,这是因为新创建的数据库需要执行相应的操作,比如插入文档等,才会被记录到本地。

接着,我们尝试着往 blog 数据库插入一个文档,此处的 post 是文档名称,后面会说到:

> db.post.insert({"content": "123"})

此时命令行中会出现 WriteResult({“nInserted” : 1}) ,这表明我们插入数据成功,同时你会在数据存放目录里(G:\blog\data)看到新增了 blog.ns 和 blog.0 两个文件。

删除数据库,删除前需请切换到该数据库,否者的话,会默认删除 test 数据库。采用如下命令:

> db.dropDatabase()

以上操作截图如下:

2.2.2 集合操作

不同集合组成了一个数据库。接下来,针对某一个数据库,来说说集合的操作。

要查看数据里的集合,可通过 show collections 命令,若当前数据库没有文档,则什么也不会输出,反之则输入对应的文档和 system.indexes

> show collections

以下命令创建一个名为 item 的集合:

> db.createCollection('item')

你也可以直接往集合里插入内容,和创建数据库一样,你无需像上面那样特意创建集合,因为当插入数据时,它就自动创建了一个集合。以下命令表示在数据库的 info 集合中,插入一个空文档,由于之前没创建过 info 集合,所以此时是自动新创建的。

> db.info.insert({})

以下命令删除一个名为 item 的集合:

> db.item.drop();

以上操作截图如下:

2.2.3 文档操作

不同文档组成了一个集合,不同的集合组成了一个数据库。接下来,针对某一个数据库下的某个集合,来说说文档的操作。

在 post 的集合中,新增单条文档和多条文档,可通过以下命令:

> db.post.insert({"content": "123"})
> db.post.insert([{"content": "456"}, {"content": "789"}])

而查找文档,则分为全部查找和指定查询,以下命令表示查找post全部的文档:

> db.post.find()

查找 content 为 456 的文档:

> db.post.find({}, {"content": "456"})

至于修改文档,则可以通过以下命令,表示将 content 为 789 的文档修改为 abc:

> db.post.update({"content": "789"}, {$set: {"content": "abc"}})

最后,可通过如下命令删除文档:

> db.post.remove({"content": "abc"})

以上命令表示删除 content 为 abc 的文档。

以上操作截图如下:

当然,mongodb还有很多很复杂,很实用的shell指令。如前面所说,这里只是简单的说明一些项目必要的shell指令,因此不一一列出。

三、改造express

前面我们说到,启动后的 express 界面和我们的要搭建的博客UI不一致,因此我们要针对它生成的文件做相应修改和调整。

先来看下生成的目录:

  • bin:存放express内部指令
  • data:我们自己定义存放数据的文件
  • node_modules:依赖包
  • public:一些静态资源,比如公用的js、css、image
  • routes:存放路由文件,可设置页面之间的跳转,以及页面载入时需执行的代码
  • views:存放视图文件,即页面模板
  • app.js:项目的入口文件
  • package.json:项目的配置文件

首先,我们首先来修改页面模板。打开 views 文件夹,你会发现有三个 .jade 文件。它是express框架的默认模板引擎,或许你和我一样,对它里面html的写法非常无感(曾经我被里面的空格错误困扰了好半天)。相比而言,我们更喜欢用 html 文件来渲染页面。嗯,那我们先着手修改掉它的模板引擎:

3.1 修改模板引擎

为了能让 html 文件作为 express 渲染页面的模板,因此我们决定采用 ejs 模板引擎,因为它和html是相互兼容的。要使用它,先安装:

> npm install ejs --save

然后是在app.js里修改模板引擎,在根目录的app.js中,有关模板引擎的是这么两句:

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

第一句:设置模板的路径是在根目录(__dirname)下的views文件夹
第二句:将模板引擎设置为以.jade为后缀名的文件

我们需要做的是,将上面两句修改为以下三句,即可:

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
app.engine('html', require("ejs").__express);

然后将 views 文件下的 jade 文件全部删除,并新增 index.html、update.html、error.html 三个html文件。

三个页面的代码分别如下:

index.html

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<title><%= title %></title>
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css">
</head>

<body>

<h3 class=""><%= name %></h3>

</body>

</html>

update.html

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<title><%= title %></title>
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css">
</head>

<body>

<h3 class=""><%= name %></h3>

</body>

</html>

error.html

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<title>错误页</title>
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css">
</head>

<body>

<div class="content">错误!</div>

</body>

</html>

或许你会好奇 <%= title %> 这样的标签,它正是模板所特有的,它的值是通过后台传至前台,然后再渲染出来。详见 http://www.embeddedjs.com/

3.2 设置路由

要使得以上3个页面能正常访问,需要在 routes 文件下设置路由。先删除 routes 下的所有js文件,然后再新增 index.js 和 update.js 文件(这里无需error.js,因为在app.js里有写)。

两个js文件代码分别如下:

index.js

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: '博客首页', name: '博客'});
});

module.exports = router;

update.js

var express = require('express');
var router = express.Router();

/* GET update page. */
router.get('/update', function(req, res, next) {
res.render('update', { title: '博客更新页', name: '博客更新'});
});

module.exports = router;

接着,我们在根目录的 app.js 里设置相应的路由:

将 app.js 里的:

var routes = require('./routes/index');
var users = require('./routes/users');

...

app.use('/', routes);
app.use('/users', users);

修改为:

var index = require('./routes/index');
var update = require('./routes/update');

...

app.use('/', index);
app.use('/', update);

最后,检验下我们的成果。在项目根目录打开命令行面板,输入以下命令:

> npm start

在浏览器里打开 http://localhost:3000/,http://localhost:3000/update, 便可以看到博客首页、博客更新页。

http://localhost:3000/errorhttp://localhost:3000/abc 之类的则会定向到错误页。

3.3 调整模板

好了,我们接着调整index.html、update.html页面,以及public里stylesheets目录下的css文件,将首页和更新页的UI界面调整成文章开头处的博客系统UI界面。并在public里javascripts目录下新增jquery.min.js文件。

index.html里新增代码:

<div class="blog-add">
<div class="blog-textarea">
<textarea name="" class="textarea-add" cols="30" rows="10"></textarea>
</div>
<p class="blog-action">
<a class="btn-publish" href="javascript:;">发布</a>
</p>
</div>

<div class="blog">
<ul class="blog-list">
<li class="blog-item">
<p class="blog-content">你好</p>
<p class="blog-extra">
<span class="date">2015-10-10</span>
<a href="javascript:;" class="delete">删除</a>
<a href="javascript:;" class="update">更新</a>
</p>
</li>
</ul>
</div>

update.html里新增代码:

<div class="blog-add">
<div class="blog-textarea">
<textarea name="" class="textarea-add" cols="30" rows="10"></textarea>
</div>
<p class="blog-action">
<a class="btn-update" href="javascript:;">更新</a>
</p>
</div>

调整后的css:

* {margin: 0;padding: 0;}
body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
a {color: #00B7FF;}
li {list-style: none;}
a {text-decoration: none;}

.blog-add .blog-textarea {margin: 20px 0 10px;padding: 10px;border: 1px solid #ccc;}
.blog-add .textarea-add {width: 100%;height: 80px;border: none;resize: none;outline: none;}
.blog-add .blog-action {line-height: 30px;text-align: right;}
.blog-add .blog-action .btn-publish,
.blog-add .blog-action .btn-update {border: 1px solid #00B7FF;padding: 5px 20px;border-radius: 3px;}
.blog-list .blog-item {padding-top: 10px;line-height: 22px;}
.blog-list .blog-item p {padding: 5px 0;word-wrap: break-word;}
.blog-list .blog-item {border-bottom: 1px dotted #ddd;}
.blog-list .blog-extra {overflow: hidden;color: #999;text-align: right;}
.blog-list .blog-extra .date {float: left;}
.blog-list .blog-extra a {border-right: 1px dotted #00B7FF;padding: 0 10px;margin-right: -6px;font-size: 12px;}

最后,得到静态的首页和更新页:

四、express与mongodb交互

通过上面的一系列操作,界面和页面路由都已经完成!接下来,就来到最重要的页面交互和数据操作了,好紧张。

我们先来理下交互流程,在首页中,我们点击 ‘发布’ 按钮,将文本框里的内容发送至后台,后台语言将数据保存到数据库,然后页面刷新,从数据库中读取博客数据,最后,将数据显示到页面。

4.1 发送数据至后台

前台给后台发送数据,当然首选ajax,在 index.html 新增js代码:

<script type="text/javascript" src="/javascripts/jquery.min.js"></script>
<script>
$(function() {

// 发布
$('.btn-publish').on('click', function() {
var blogContent = $('.textarea-add').val().trim().replace(/\n/g, '<br/>');

if (!blogContent) {
alert('内容不能为空!');
return;
}

var date = new Date(),
yy = date.getFullYear(),
MM = date.getMonth() + 1,
dd = date.getDate(),
hh = date.getHours(),
mm = date.getMinutes(),
ss = date.getSeconds();

var postData = {
'content': blogContent,
'date': yy + '-' + MM + '-' + dd + ' ' + hh + ':' + mm + ':' + ss
};

$.ajax({
url: '/',
type: 'post',
data: postData,
success: function(data){
alert('发布成功!');
location.href = '/';
},
error: function(data){
alert('发布失败!');
location.href = 'error';
}
});

});

});
</script>

4.2 node.js接收数据并将数据保存到数据库

在这里我们使用 mongoose 接收数据。

mongoose 是一个文档对象模型库(ODM),它的语法和 mongodb 里的 shell 命令是一样的。如果你使用过 node.js 直接操作 mongodb,你会发现代码中会出现很多嵌套、回调以及各种潜在问题。但有了 mongoose,你可以直接在 node.js 里使用 mongoose 自身的语法,不仅代码简洁,操作数据方便,而且避免了很多额外的问题。

如果你想了解 mongoose 更多的内容,可访问:

老规矩,要使用它,就得先安装它:

> npm install mongoose --save

安装完毕后,在 data 文件夹下新增 mongoose.js 文件,它的代码如下:

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/blog');

var blogSchema = new mongoose.Schema({
content: {type: String, unique:true}, // unique 保证数据的唯一,但有时候不管用
date: String
}, {collection: 'post'});

var post = mongoose.model('post', blogSchema);

module.exports = post;

然后在根目录下 app.js 里的 var app = express(); 下一行增加以下代码:

global.post = require('./data/mongoose');

因为前面ajax是将数据 post 到 index.html 页面,因此我们需要在 index.js 处理 post 的请求。在 index.js 里新增代码:

/* POST home page. */
router.post('/', function(req, res) {
var content = req.body.content;
var date = req.body.date;

if (content && date) {
var newPost = new post({
content: content,
date: date
});

newPost.save(function (err) {
if (err) {
console.error(err);
return;
}
// newPost is saved!
console.log('保存成功!');
res.send(200);
});
}
});

此时,我们使用以下命令重启服务:

> npm start

刷新页面,然后在文本框里输入 ‘夜晚,这是一个很安静的夜晚!’ ,点击 ‘发布’ 按钮后,会弹出 ‘发布成功!’ 的提示。

然后,我们在操作数据库的命名行面板中,输入查找命令,即可打印出我们刚才发布的内容,这也说明数据在数据库里保存成功了。

4.3 读取数据库数据并将数据显示至页面

保存完数据后,我们刷新浏览器的页面,但是发现刚才保存的 ‘夜晚,这是一个很安静的夜晚!’ 这条数据并未在页面中显示出来。这是为什么?

因为在刚才的操作中,我们只是点击 ‘发布’ 按钮,将数据 post 到博客首页,并将数据保存到数据库。但是博客首页刷新后,我们并没有写任何读取数据库的代码。

因此,需要在博客首页刷新时(也就是 get 时),去读取数据库,并把读取的数据发送给前端模板,再通过模板把这些数据渲染出来。

首先,我们将 index.js 里的:

/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: '博客首页', name: '博客'});
});

修改为:

/* GET home page. */
router.get('/', function(req, res, next) {

post.find({}, function(err, docs) {
if (err) {
console.error(err);
return;
}
// docs 是包含了符合条件的多个文档的一个数组
// console.log(docs);
res.render('index', { title: '博客首页', name: '博客', content: docs.reverse()});
});

});

在这里,docs 是读取数据库后返回的数据,它是一个数组,我使用了 docs.reverse() 对数组进行反转,也就是让最新的数据,渲染在博客列表的最前面。

然后,我们再回到模板里。因为,后台返回给前台的数据是动态的,因此也需要对 index.html 中的列表部分进行修改,将 index.html 里的:

<div class="blog">
<ul class="blog-list">
<li class="blog-item">
<p class="blog-content">你好</p>
<p class="blog-extra">
<span class="date">2015-10-10</span>
<a href="javascript:;" class="delete">删除</a>
<a href="javascript:;" class="update">更新</a>
</p>
</li>
</ul>
</div>

修改为:

<div class="blog">
<ul class="blog-list">
<% for(var i=0; i<content.length; i++) { %>
<li class="blog-item">
<p class="blog-content"><%- content[i].content %></p>
<p class="blog-extra">
<span class="date"><%= content[i].date %></span>
<a href="javascript:;" class="delete" data-content="<%= content[i].content %>">删除</a>
<a href="javascript:;" class="update" data-content="<%= content[i].content %>">更新</a>
</p>
</li>
<% } %>
</ul>
</div>

关于模板的用法和写法,可参考 ejs 的相关文档。

好了,我们再次刷新页面,便能看到 ‘夜晚,这是一个很安静的夜晚!’ 这条数据了。

是不是感觉很棒!

文章写到这里,我们已经完成了 express 的搭建、模板的使用、mongodb 数据的存储和读取等这些非常重要的步骤,这也意味着博客系统已经完成一大半了。

接下来,我们继续完成博客的删除和更新。

4.4 数据的删除与更新

在前面的操作中,细心的你或许已经注意到 index.html 列表里有这样的代码:

<a href="javascript:;" class="delete" data-content="<%= content[i].content %>">删除</a>
<a href="javascript:;" class="update" data-content="<%= content[i].content %>">更新</a>

是的,这里的 content[i].content 就是每条博客的内容。当点击 ‘删除’ 和 ‘更新’ 这个按钮时,我们会根据它的 data-content 属性来获取这条博客的内容,然后对符合内容的数据进行删除和更新操作。

4.5 数据的删除

和发送博客类似,这里的删除操作也是通过发送 ajax 给后台,在 index.html 里的js部分,新增以下js代码:

// 删除
$('.delete').on('click', function() {
var deleteContent = $(this).attr('data-content');

var postData = {
'deleteContent': deleteContent
};

if (confirm('您确定要删除这条博客吗?')) {
$.ajax({
url: '/',
type: 'post',
data: postData,
success: function(data){
// alert('成功!');
location.href = '/';
},
error: function(data){
// alert('失败!');
location.href = 'error';
}
});
}
});

前台页面发送了 post 提交请求,那后台就需要处理这个 post 请求。于是,index.js 新增删除数据的代码,即 index.js 中的 router.post 部分更新为:

/* POST home page. */
router.post('/', function(req, res) {
var content = req.body.content;
var date = req.body.date;

if (content && date) {
var newPost = new post({
content: content,
date: date
});

newPost.save(function (err) {
if (err) {
console.error(err);
return;
}
// newPost is saved!
console.log('保存成功!');
res.send(200);
});
}

var deleteContent = req.body.deleteContent;

if (deleteContent) {
post.remove({content: deleteContent}, function(err) {
if (err) {
console.error(err);
return;
}
console.log('删除成功!');
res.send(200);
});
}
});

嗯,删除数据的功能基本完成。我们运行下重启服务的命令:

> npm start

刷新浏览器页面,发布一条内容为 ‘abcd’ 的博客后,然后点 ‘删除’ 按钮,首先它会提示你 ‘您确定要删除这条博客吗?’ ,点击 ‘确定’ 按钮后,页面刷新, ‘abcd’ 这条博客就在页面里被删除了。你也可以在数据库命令面板中运行 db.post.find(),查看该条数据是否真的已删除。

4.6 数据的更新

数据的更新有点特别,这点在文章的开头也能看出。因为博客的更新是在 update.html 完成的,你可以先回到前面看下博客更新页的UI界面。

然后,我们来描述下博客更新的流程,主要分为3步:

  1. 在博客首页点击 ‘更新’ 按钮后,将该条博客的内容作为更新页地址的参数,并且此时,页面跳转到博客更新页(update.html)。简单来说,就是把博客内容带到更新页。
  2. 在博客更新页读取url里的参数,并将它赋值给文本框中。然后在文本框修改博客内容,点击文本框底部右边的 ‘更新’ 按钮,将文本框里的内容通过ajax的方式 post 到博客首页。其实这里的更新操作和博客首页的发布博客类似。
  3. post 到博客首页后,页面将会跳转到博客首页,博客首页在后台处理 post 请求,mongoose代码更新该条博客数据,并将新的博客内容显示出来。

流程说完,接着我们来把它们转换成代码:

第一步,在 index.html 中新增js代码:

// 更新跳转
$('.update').on('click', function() {
var updateContent = $(this).attr('data-content');
location.href = '/update?updateBlog=' + updateContent;
});

第二步,在 update.html 中新增js代码:

<script type="text/javascript" src="/javascripts/jquery.min.js"></script>
<script>
$(function() {

// 从url读取要更新的内容,简单粗暴处理
var oldContent = decodeURI(window.location.search.substr(12));

// 设置它到文本域,并保留换行
$('.textarea-add').val(oldContent.replace(/\<br\/>/g, '\n'));

// 更新
$('.btn-update').on('click', function() {
var updateContent = $('.textarea-add').val().trim().replace(/\n/g, '<br/>');

if (updateContent === oldContent) {
alert('内容没有更新!');
return;
}

var postData = {
'oldContent': oldContent,
'updateContent': updateContent
};

$.ajax({
url: '/',
type: 'post',
data: postData,
success: function(data){
alert('更新成功!');
location.href = '/';
},
error: function(data){
alert('更新失败!');
location.href = 'error';
}
});
});

});
</script>

这里需要注意下,url里的参数必须 decodeURI 转码下才能赋值给文本框,并且html标签里的换行(<br/>)与文本框的换行(\n)也是不同的,在读取操作时也要进行特殊处理。还有,如果博客内容没有发生变化,要给予提示。

第三步,将 index.js 中的 router.post 部分更新为:

/* POST home page. */
router.post('/', function(req, res) {
var content = req.body.content;
var date = req.body.date;

if (content && date) {
var newPost = new post({
content: content,
date: date
});

newPost.save(function (err) {
if (err) {
console.error(err);
return;
}
// newPost is saved!
console.log('保存成功!');
res.send(200);
});
}

var deleteContent = req.body.deleteContent;

if (deleteContent) {
post.remove({content: deleteContent}, function(err) {
if (err) {
console.error(err);
return;
}
console.log('删除成功!');
res.send(200);
});
}

var oldContent = req.body.oldContent,
updateContent = req.body.updateContent;

if (oldContent && updateContent) {
post.update({content: oldContent}, {$set: {'content': updateContent}}, function(err) {
if (err) {
console.error(err);
return;
}
console.log('更新成功!');
res.send(200);
});
}
});

老规矩,我们运行重启服务的命令,来检测下更新博客的功能:

> npm start

刷新浏览器页面,首先我们发布一条内容为 ‘123’ 的博客后,然后点 ‘更新’ 按钮,页面跳转到博客更新页,在文本框里将 ‘123’ 更新为 ‘456’,再点 ‘更新’ 按钮后,页面会提示 ‘更新成功!’ ,并且此时,页面将跳转到博客首页,你也将看到之前 ‘123’ 的博客被更新为 ‘456’。

至此,我们的博客系统就 ‘完美竣工’ 了!

五、启动项目

博客系统的源码我已打包出来,点击底下链接进行下载:

极简博客系统

下载完后,首先在下载项目的根目录打开命令行面板,安装依赖:

> npm install

依赖安装完后,在任意目录,打开另外一个命令行面板,设置数据库目录,并启动 mongodb 数据库。通过以下命令(数据存在根目录 data 文件夹下):

> mongod.exe --dbpath 项目路径\data

回到项目根目录的命令行面板,输入以下命令,启动服务:

> npm start

在浏览器中,打开 http://localhost:3000/

六、结语

虽然是一个极简的博客发布系统,但由于其中牵涉到前端web、模板引擎、服务器端框架、数据库存储及操作等各项技术,它们中的每一项都有自己的体系,况且要把这些技术恰如其分的组合起来,去完成一个web应用的开发,还真不是那么轻松的事。更何况,本文所应用到的,都只是它们的皮毛而已。

最后,以上内容均为个人研究和摸索,可能存在不足,欢迎邮件指出,同时也希望本文内容对你有所帮助!