1. 入門
高度包容、快速而極簡的 Node.js Web 框架
1.1 安裝
npm install express --save
1.2 hello world
- 創(chuàng)建名為
app.js的文件,然后添加以下代碼
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
注釋: 此應用程序以“Hello World!”響應針對根 URL (/)路由的請求。對于其他所有路徑,它將以 404 Not Found 進行響應。
1.3 Express 生成器
可使用應用程序生成器工具 (express) 快速創(chuàng)建應用程序框架。
- 安裝
express-generator生成器
(1) 全局安裝:npm i express-generator -g
(2) 查看命令:express -h
(3) 查看版本:express --version - 創(chuàng)建名為
server的Express應用程序
express server - 安裝依賴
cd server
npm install - 啟動程序
npm start - 項目文件介紹
-
bin/www項目入口文件 -
public資源文件 -
routes路由 -
views視圖
- 使用
html模板替換jade模板
- 安裝
ejs
npm i ejs --save - 修改
app.js
const ejs = require('ejs');
//app.set('view engine', 'jade');
app.engine('.html', ejs.__express);
app.set('view engine', 'html');
1.4 基本路由
- 路由用于確定應用程序如何響應對特定端點的客戶機請求。
- 每個路由可以具有一個或多個處理程序函數(shù),這些函數(shù)在路由匹配時執(zhí)行。
- 路由定義采用以下結構:
app.METHOD(PATH, HANDLER)
其中:app是express的實例。METHOD是 HTTP 請求方法。PATH是服務器上的路徑。HANDLER是在路由匹配時執(zhí)行的函數(shù)。 - 簡單路由演示
- 以主頁上的
Hello World!進行響應:
app.get('/', function (req, res) {
res.send('Hello World!');
});
- 在根路由 (
/) 上(應用程序的主頁)對POST請求進行響應:
app.post('/', function (req, res) {
res.send('Got a POST request');
});
- 對
/user路由的PUT請求進行響應:
app.put('/user', function (req, res) {
res.send('Got a PUT request at /user');
});
- 對
/user路由的DELETE請求進行響應:
app.delete('/user', function (req, res) {
res.send('Got a DELETE request at /user');
});
1.5 靜態(tài)文件
- 為了提供諸如圖像、
CSS文件和JavaScript文件之類的靜態(tài)文件,請使用Express中的express.static內(nèi)置中間件函數(shù)。 - 將包含靜態(tài)資源的目錄的名稱傳遞給
express.static中間件函數(shù),以便開始直接提供這些文件。例如,使用以下代碼在名為public的目錄中提供圖像、CSS文件和JavaScript文件:
app.use(express.static('public'));
- 可以訪問位于
public目錄中的文件
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html - 要使用多個靜態(tài)資源目錄,請多次調用
express.static中間件函數(shù):
app.use(express.static('public'));
app.use(express.static('files'));
- 向
express.static函數(shù)提供的路徑相對于您在其中啟動node進程的目錄。如果從另一個目錄運行Express應用程序,那么對于提供資源的目錄使用絕對路徑會更安全:
app.use('/static', express.static(__dirname + '/public'));
1.6 常見問題及解答
- 如何定義模型?
Express沒有數(shù)據(jù)庫概念。此概念留給第三方Node模塊實現(xiàn),因此可以接入幾乎任何數(shù)據(jù)庫。 - 如何處理
404響應?
Express執(zhí)行了所有中間件函數(shù)和路由,且發(fā)現(xiàn)它們都沒有響應。您需要做的只是在堆棧的最底部(在其他所有函數(shù)之下)添加一個中間件函數(shù)來處理404響應:
app.use(function(req, res, next) {
res.status(404).send('Sorry cant find that!');
});
- 如何設置錯誤處理程序?
錯誤處理中間件的定義方式與其他中間件基本相同,差別在于錯誤處理中間件有四個自變量而不是三個,專門具有特征符(err, req, res, next):
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
注意:錯誤處理中間件始終采用四個自變量。必須提供四個自變量,以將函數(shù)標識為錯誤處理中間件函數(shù)。否則,next 對象將被解釋為常規(guī)中間件,從而無法處理錯誤。
2. 指南
3. API參考
3.1 express()
Methods
express.json()
express.static()
express.Router()
express.urlencoded()
3.2 Application
Properties
app.locals
app.mountpath
Events
mount
Methods
app.all()
app.delete()
app.disable()
app.disabled()
app.enable()
app.enabled()
app.engine()
app.get()
app.get()
app.listen()
app.METHOD()
app.param()
app.path()
app.post()
app.put()
app.render()
app.route()
app.set()
app.use()
3.3 Request
Properties
req.app
req.baseUrl
req.body
包含在request body請求體中提交的鍵-值對數(shù)據(jù)。默認情況下,它是 undefined。在你使用body解析中間件時才會被填充,例如:body-parser 或者 multer。
下面這個例子展示了如何使用body解析中間件來填充req.body。
var app = require('express')();
var bodyParser = require('body-parser');
var multer = require('multer');
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(multer()); // for parsing multipart/form-data
app.post('/', function (req, res) {
console.log(req.body);
res.json(req.body);
})
req.cookies
當使用 cookie-parser 中間件時,此屬性是一個包含由請求發(fā)送的cookie的對象。如果請求不包含cookie,則默認為{}。
// Cookie: name=tj
req.cookies.name
// => "tj"
如果cookie已經(jīng)簽名,則必須使用req.signedCookies。
有關更多信息、問題或關注,請參閱cookie-parser。
req.fresh
req.hostname
req.ip
req.ips
req.method
req.originalUrl
req.params
- 返回一個匹配路由參數(shù)的
object對象。例如,如果路由路徑為/user/:name,那么可以通過req.params.name取到name字段值。默認返回值為空對象{}。
// GET /user/tj
req.params.name
// => "tj"
注意:與vue-router用法類似。
- 如果在路由中定義了正則表達式,使用
req.params[n]可以獲取捕獲組。其中,n表示第n個捕獲組。該規(guī)則適用于未定義通配符匹配的字符串路由,例如:/file/*。
// GET /file/javascripts/jquery.js
req.params[0]
// => "javascripts/jquery.js"
- 如果需要在
req.params中對參數(shù)進行更改,可以使用app.param處理程序。 更改僅適用于路由路徑中已定義的參數(shù)。 - 在中間件或路由處理程序中對
req.params對象所做的任何更改都將被重置。 -
Express將自動解碼req.params中的值。(使用decodeURIComponent)。
req.path
req.protocol
req.query
一個包含路由中每個查詢字符串參數(shù)的屬性的對象。如果沒有查詢字符串,就是一個空對象{}。
// GET /search?q=tobi+ferret
req.query.q
// => "tobi ferret"
// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
req.query.order
// => "desc"
req.query.shoe.color
// => "blue"
req.query.shoe.type
// => "converse"
req.route
req.secure
req.signedCookies
req.stale
req.subdomains
req.xhr
Methods
req.accepts()
req.acceptsCharsets()
req.acceptsEncodings()
req.acceptsLanguages()
req.get()
req.is()
req.param()
已經(jīng)被廢棄,推薦直接使用
req.params,req.body和req.query。
返回當前“name”參數(shù)的值。
// ?name=tobi
req.param('name')
// => "tobi"
// POST name=tobi
req.param('name')
// => "tobi"
// /user/tobi for /user/:name
req.param('name')
// => "tobi"
查找的順序如下:
req.paramsreq.bodyreq.query
如果在任何請求對象中都沒有找到參數(shù),您可以指定defaultValue來設置默認值。
必須使用body解析中間件,以便req.param()可以正常工作。 更多細節(jié)參考:req.body 。
req.range()
3.4 Response
Properties
res.app
res.headersSent
res.locals
Methods
res.append()
res.attachment()
res.cookie()
res.cookie(name, value [, options])
設置cookie鍵值對,value參數(shù)可以是一個字符串或者可以轉化為json的對象。options參數(shù)是一個包含以下屬性的對象。
| 屬性 | 類型 | 描述 |
|---|---|---|
domain |
String | cookie的域名。默認為應用程序的域名。 |
encode |
Function | 用于cookie值編碼的同步函數(shù)。默認為“encodeURIComponent”。 |
expires |
Date | 相對于GMT標準的過期時間。如果沒有指定或設置為0,則創(chuàng)建會話cookie。 |
httpOnly |
Boolean | 是否只能由web服務器訪問的cookie標記。 |
maxAge |
Number | 用于設置相對于當前時間(以毫秒為單位)的到期時間。 |
path |
String | cookie存儲路徑,默認為 “/”。 |
secure |
Boolean | 標記cookie僅允許被https請求使用。 |
signed |
Boolean | 表明cookie是否被簽名。 |
sameSite |
Boolean or String | 參考 |
res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true });
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
res.clearCookie()
res.clearCookie(name [, options])
清除由名稱指定的cookie。有關options對象的詳細信息,請參閱res.cookie()。
res.cookie('name', 'tobi', { path: '/admin' });
res.clearCookie('name', { path: '/admin' });