1、準(zhǔn)備工作:
文本工具:VSCodeSetup-1.9.1.exe
nodejs 版本:node-v6.9.1-x64.msi
數(shù)據(jù)庫-mongodb:mongodb-win32-x86_64-2008plus-ssl-3.4.2-signed.msi
首先,我們新建一個(gè)目錄 myblog,在該目錄下運(yùn)行 npm init 生成一個(gè) package.json
然后安裝 express 并寫入 package.json:
npm i express@4.14.0 --save
新建 index.js,添加如下代碼:
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('hello, express');
});
app.listen(3000);
以上代碼的意思是:生成一個(gè) express 實(shí)例 app,掛載了一個(gè)根路由控制器,然后監(jiān)聽 3000 端口并啟動(dòng)程序。運(yùn)行 node index,打開瀏覽器訪問 localhost:3000 時(shí),頁面應(yīng)顯示 hello, express。
這是最簡單的一個(gè)使用 express 的例子,后面會(huì)介紹路由及模板的使用。
1.1 supervisor
在開發(fā)過程中,每次修改代碼保存后,我們都需要手動(dòng)重啟程序,才能查看改動(dòng)的效果。使用 supervisor 可以解決這個(gè)繁瑣的問題,全局安裝 supervisor:
npm install -g supervisor
運(yùn)行 supervisor --harmony index 啟動(dòng)程序,如下所示:
supervisor 會(huì)監(jiān)聽當(dāng)前目錄下 node 和 js 后綴的文件,當(dāng)這些文件發(fā)生改動(dòng)時(shí),supervisor 會(huì)自動(dòng)重啟程序。
前面我們只是掛載了根路徑的路由控制器,現(xiàn)在修改 index.js 如下:
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('hello, express');
});
app.get('/users/:name', function(req, res) {
res.send('hello, ' + req.params.name);
});
app.listen(3000);
以上代碼的意思是:當(dāng)訪問根路徑時(shí),依然返回 hello, express,當(dāng)訪問如 localhost:3000/users/nswbmw 路徑時(shí),返回 hello, nswbmw。路徑中 :name 起了占位符的作用,這個(gè)占位符的名字是 name,可以通過 req.params.name 取到實(shí)際的值。
小提示:express 使用了 path-to-regexp 模塊實(shí)現(xiàn)的路由匹配。
不難看出:req 包含了請求來的相關(guān)信息,res 則用來返回該請求的響應(yīng)
下面介紹幾個(gè)常用的 req 的屬性:
req.query: 解析后的 url 中的 querystring,如 ?name=haha,req.query 的值為 {name: 'haha'}
req.params: 解析 url 中的占位符,如 /:name,訪問 /haha,req.params 的值為 {name: 'haha'}
req.body: 解析后請求體,需使用相關(guān)的模塊,如 body-parser,請求體為 {"name": "haha"},則 req.body 為 {name: 'haha'}
2.1 express.Router
上面只是很簡單的路由使用的例子(將所有路由控制函數(shù)都放到了 index.js),但在實(shí)際開發(fā)中通常有幾十甚至上百的路由,都寫在 index.js 既臃腫又不好維護(hù),這時(shí)可以使用 express.Router 實(shí)現(xiàn)更優(yōu)雅的路由解決方案。在 myblog 目錄下創(chuàng)建空文件夾 routes,在 routes 目錄下創(chuàng)建 index.js 和 users.js。最后代碼如下:
index.js
var express = require('express');
var app = express();
var indexRouter = require('./routes/index');
var userRouter = require('./routes/users');
app.use('/', indexRouter);
app.use('/users', userRouter);
app.listen(3000);
routes/index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('hello, express');
});
module.exports = router;
routes/users.js
var express = require('express');
var router = express.Router();
router.get('/:name', function(req, res) {
res.send('hello, ' + req.params.name);
});
module.exports = router;
以上代碼的意思是:我們將 / 和 /users/:name 的路由分別放到了 routes/index.js 和 routes/users.js 中,每個(gè)路由文件通過生成一個(gè) express.Router 實(shí)例 router 并導(dǎo)出,通過 app.use 掛載到不同的路徑。這兩種代碼實(shí)現(xiàn)了相同的功能,但在實(shí)際開發(fā)中推薦使用 express.Router 將不同的路由分離到不同的路由文件中。
效果圖:
3.1 ejs
模板引擎有很多,ejs 是其中一種,因?yàn)樗褂闷饋硎趾唵危遗c express 集成良好,所以我們使用 ejs。安裝 ejs:
npm i ejs --save
修改 index.js 如下:
index.js
var path = require('path');
var express = require('express');
var app = express();
var indexRouter = require('./routes/index');
var userRouter = require('./routes/users');
app.set('views', path.join(__dirname, 'views'));// 設(shè)置存放模板文件的目錄
app.set('view engine', 'ejs');// 設(shè)置模板引擎為 ejs
app.use('/', indexRouter);
app.use('/users', userRouter);
app.listen(3000);
通過 app.set 設(shè)置模板引擎為 ejs 和存放模板的目錄。在 myblog 下新建 views 文件夾,在 views 下新建 users.ejs,添加如下代碼
views/users.ejs
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
</style>
</head>
<body>
<h1><%= name.toUpperCase() %></h1>
<p>hello, <%= name %></p>
</body>
</html>
routes/users.js
var express = require('express');
var router = express.Router();
router.get('/:name', function(req, res) {
res.render('users', {
name: req.params.name
});
});
module.exports = router;
通過調(diào)用 res.render 函數(shù)渲染 ejs 模板,res.render 第一個(gè)參數(shù)是模板的名字,這里是 users 則會(huì)匹配 views/users.ejs,第二個(gè)參數(shù)是傳給模板的數(shù)據(jù),這里傳入 name,則在 ejs 模板中可使用 name。res.render 的作用就是將模板和數(shù)據(jù)結(jié)合生成 html,同時(shí)設(shè)置響應(yīng)頭中的 Content-Type: text/html,告訴瀏覽器我返回的是 html,不是純文本,要按 html 展示。現(xiàn)在我們訪問 localhost:3000/users/haha,如下圖所示:
上面代碼可以看到,我們在模板 <%= name.toUpperCase() %> 中使用了 JavaScript 的語法 .toUpperCase() 將名字轉(zhuǎn)化為大寫,那這個(gè) <%= xxx %> 是什么東西呢?ejs 有 3 種常用標(biāo)簽:
<% code %>:運(yùn)行 JavaScript 代碼,不輸出
<%= code %>:顯示轉(zhuǎn)義后的 HTML內(nèi)容
<%- code %>:顯示原始 HTML 內(nèi)容
注意:<%= code %> 和 <%- code %> 都可以是 JavaScript 表達(dá)式生成的字符串,當(dāng)變量 code 為普通字符串時(shí),兩者沒有區(qū)別。當(dāng) code 比如為 這種字符串時(shí),<%= code %> 會(huì)原樣輸出 ,而 <%- code %> 則會(huì)顯示 H1 大的 hello 字符串。
下面的例子解釋了 <% code %> 的用法:
Data
supplies: ['mop', 'broom', 'duster']
<ul>
<% for(var i=0; i<supplies.length; i++) {%>
<li><%= supplies[i] %></li>
<% } %>
</ul>
//Result
<ul>
<li>mop</li>
<li>broom</li>
<li>duster</li>
</ul>
更多 ejs 的標(biāo)簽請看 官方文檔。
3.2 includes
我們使用模板引擎通常不是一個(gè)頁面對(duì)應(yīng)一個(gè)模板,這樣就失去了模板的優(yōu)勢,而是把模板拆成可復(fù)用的模板片段組合使用,如在 views 下新建 header.ejs 和 footer.ejs,并修改 users.ejs:
views/header.ejs
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
</style>
</head>
<body>
views/footer.ejs
</body>
</html>
views/users.ejs
<%- include('header') %>
<h1><%= name.toUpperCase() %></h1>
<p>hello, <%= name %></p>
<%- include('footer') %>
我們將原來的 users.ejs 拆成出了 header.ejs 和 footer.ejs,并在 users.ejs 通過 ejs 內(nèi)置的 include 方法引入,從而實(shí)現(xiàn)了跟以前一個(gè)模板文件相同的功能。
ps:拆分模板組件通常有兩個(gè)好處:
模板可復(fù)用,減少重復(fù)代碼
主模板結(jié)構(gòu)清晰
######注意:要用 <%- include('header') %> 而不是 <%= include('header') %>