原文:Introduction to Express 笔记:涂鸦码龙
安装 package.json 中手动添加 Express 依赖
1
2
3
4
5
6
7
8
{
"name" : "demo1" ,
"description" : "First Express app" ,
"version" : "0.0.1" ,
"dependencies" : {
"express" : "3.x"
}
}
相同的目录运行:
命令行安装 Express 直接运行:
安装完后可以用 express 在命令行生成应用。
添加 app.js 文件,写个最简单的应用,创建一个 Express 实例,开始监听特定的端口 :
1
2
3
4
var express = require ('express' );
var app = express();
app.listen(3000 );
运行 node app
没发生任何事情。
定义路由 我们给应用添加一些简单的路由,Express 可以响应各种 HTTP 请求:
1
2
3
4
5
6
7
8
app.get(some url, do something);
app.get(some other url, do something else );
app.post(some url, do more stuff);
我们写个真实的例子,给应用添加主页:
1
2
3
app.get('/' , function (request, response ) {
response.send("This would be some HTML" );
});
注意 Express 为 response 对象添加了 send()
方法,一些模板代码可以处理响应。重启应用,访问 http://localhost:3000/ 看看。
request.send() API 智能处理不同类型的数据,假如你想为网站添加简单的基于 JSON 的 API ,Express 可以把返回结果转换成 JSON 并设置适当的响应头。
1
2
3
app.get('/api' , function (request, response ) {
response.send({name :"Raymond" ,age :40 });
});
可想而知,添加更多的路由,并处理所需的响应,就可以构建一个应用。
通用的博客应用 跳过 package.json 文件,因为除了 name 属性不一样,其它项都一样。来看 app.js 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var express = require ('express' );
var app = express();
app.get('/' , function (req, res ) {
res.sendfile('./views/index.html' );
});
app.get('/about' , function (req, res ) {
res.sendfile('./views/about.html' );
});
app.get('/article' , function (req, res ) {
res.sendfile('./views/article.html' );
});
app.listen(3000 );
我们把 send 换成了 sendfile 。与其把大段的 HTML 字符串放到 app.js 文件里,不如增加三个路由,主页,关于页,文章页。
添加 HTML 主页:
HTML 代码
这里并没什么特别的,Express 将返回纯静态的 HTML 。关于页和文章页只不过把 title 和 h1 值改了。
由静态到动态 Express 支持各种模板引擎,express 命令行可以添加对 Jade,EJS,JSHTML 和 Hogan 的支持。根据 Express 文档,任何模版引擎只要符合特定的签名就可以生效。推荐从 consolidate.js 库(模版引擎集合)里面查找喜欢的模版引擎。
我是 Handlebars 的超级粉,我的许多客户端应用都用它,服务器端自然也少不了它。要用 Handlebars 还需要安装包装库 hbs 。
1
2
3
4
5
6
7
8
9
{
"name" : "blog2" ,
"description" : "Blog app" ,
"version" : "0.0.1" ,
"dependencies" : {
"express" : "3.x" ,
"hbs" :"*"
}
}
然后更新 app.js 使用此引擎:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var express = require ('express' );
var app = express();
var hbs = require ('hbs' );
app.set('view engine' , 'html' );
app.engine('html' , hbs.__express);
app.get('/' , function (req, res ) {
res.render('index' );
});
app.get('/about' , function (req, res ) {
res.render('about' );
});
app.get('/article' , function (req, res ) {
res.render('article' );
});
app.listen(3000 );
为了使用 Handlebars ,我们通过 require 把 HBS 包装库引入,然后让 Express 使用它。 默认情况下,Handlebars 会解析包含了特定引擎扩展的文件,这里是 something.hbs
。但也可以使用 “view engine
”指令告诉 Express 动态解析 HTML 文件。这样我的编辑器可以提供良好的代码校验和语法高亮。通过 app.engine
真正加载引擎。
最终路由用了新的 render
方法,Express 默认使用 views 文件夹,因此我们可以省略。由于 Express 记住了我们要解析的扩展名,所以它也可以省略。res.render('something')
实际等于告诉 Express 查找 views/something.html
。Express 基于模板引擎规则解析它,并返回到浏览器。
主页显示博客条目 我们可以连接到 MySQL 或者 Mongo,这里我们创建一个静态的数据集,取名 blog.js ,它提供获取一组条目和获取一个条目功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var entries = [
{"id" :1 , "title" :"Hello World!" , "body" :"This is the body of my blog entry. Sooo exciting." , "published" :"6/2/2013" },
{"id" :2 , "title" :"Eggs for Breakfast" , "body" :"Today I had eggs for breakfast. Sooo exciting." , "published" :"6/3/2013" },
{"id" :3 , "title" :"Beer is Good" , "body" :"News Flash! Beer is awesome!" , "published" :"6/4/2013" },
{"id" :4 , "title" :"Mean People Suck" , "body" :"People who are mean aren't nice or fun to hang around." , "published" :"6/5/2013" },
{"id" :5 , "title" :"I'm Leaving Technology X and You Care" , "body" :"Let me write some link bait about why I'm not using a particular technology anymore." , "published" :"6/10/2013" },
{"id" :6 , "title" :"Help My Kickstarter" , "body" :"I want a new XBox One. Please fund my Kickstarter." , "published" :"6/12/2013" }];
exports.getBlogEntries = function ( ) {
return entries;
}
exports.getBlogEntry = function (id ) {
for (var i=0 ; i < entries.length; i++) {
if (entries[i].id == id) return entries[i];
}
}
我们还可以提供添加,编辑和删除,这里到此为止。再更新下 app.js :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var express = require ('express' );
var app = express();
var hbs = require ('hbs' );
var blogEngine = require ('./blog' );
app.set('view engine' , 'html' );
app.engine('html' , hbs.__express);
app.use(express.bodyParser());
app.get('/' , function (req, res ) {
res.render('index' ,{title :"My Blog" , entries :blogEngine.getBlogEntries()});
});
app.get('/about' , function (req, res ) {
res.render('about' , {title :"About Me" });
});
app.get('/article/:id' , function (req, res ) {
var entry = blogEngine.getBlogEntry(req.params.id);
res.render('article' ,{title :entry.title, blog :entry});
});
app.listen(3000 );
我们用 require
引入数据集,如此可以调用它得到条目。
在主页,我们给 render
API 传两个参数,参数是一个对象,包含 title
和 entries
属性。title 的值时字符串,但是 entries 调用 blogEngine
API 。我们传的任何数据将对模版生效,主页模版需要调整。
主页模版代码
即使你从没用过 Handlebars ,仍旧能猜到这里的含义。#each
指令将循环一个数组,{{}} 表示从博客条目列表取到的参数。
创建一个布局 你肯定关心剩下的 HTML 怎么改,Express 用了模版引擎会自动支持布局。这意味着我可以创建通用的网站设计布局,Express 将利用它构造特定的页面。按照约定,它取名 layout.something
,“something”是你使用的特定扩展。我们用了 HTML ,它就是 layout.html
。
layout.html 代码
关于页面没什么亮点,我们跳过,下面看文章路由。URL 现在包含了标记 :id
,Express 可以创建动态的 URL ,用于对应请求参数。我们定义的链接像这样:/article/
理论上,每一个博客条目需要一个路由,但是创建一个抽象的路由匹配这些请求效果更好。 bodyParser
(这一特性来源于 Connect 框架,的确对我很有帮助,它不仅支持查询字符串,而且支持表单主体,几乎每个 Express 应用都会用到它。)
显示个别文章 由于 URL 结尾包含动态值,我们可以把它传给 blogEngine
对象,用得到的结果作为视图的变量。
article.html 文件
现在我们创建了一个真正动态,但是难看的应用,这是新主页:
这是特定的博客条目:
润色! 我们加点基本的样式,让应用变好看点。Express 提供了简洁的方式添加图像,JavaScript 库和样式表之类的静态资源,简单定义一个静态文件夹,任何请求将从这个文件夹查找文件。
1
app.use(express.static('public' ));
此时,如果请求 /foo.css,public 文件夹存在 foo.css 文件,将返回它。我把 Bootstrap 和 jQuery 副本放到了 public 文件夹。
然后在我的 layout.html ,我可以引用这些资源。这是链接 bootstrap.css 的例子:
代码实例
Express 将自动检查 public 文件夹,可以有多个静态文件夹,甚至可以自定义 URL 前缀。最终效果是极好的。
主页:
文章页:
进阶? 延伸阅读: