欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

node.js Web應用框架Express入門指南

 更新時間:2014年05月28日 09:16:52   作者:  
這篇文章主要介紹了node.js Web應用框架Express入門指南,從安裝到各種技術的應用,都進行了講解,是一篇不錯的Express入門教程,需要的朋友可以參考下

一、安裝

復制代碼 代碼如下:
$ npm install express

或者在任何地方使用可執(zhí)行的 express(1) 安裝:

復制代碼 代碼如下:
\# 譯注:強烈建議這種方式
$ npm install -g express

二、快速上手

最快上手 express 的方法是利用可執(zhí)行的 express(1) 來生成一個應用,如下所示:

創(chuàng)建一個 app:

復制代碼 代碼如下:

$ npm install -g express
$ express /tmp/foo && cd /tmp/foo

安裝依賴包:
復制代碼 代碼如下:

$ npm install -d

啟動服務器:
復制代碼 代碼如下:

$ node app.js

三、創(chuàng)建一個服務器

要創(chuàng)建一個 express.HTTPServer 實例,只需調用 createServer() 方法。 通用這個應用實例,我們可以定義基于 HTTP 動作(HTTP Verbs)的路由,以 app.get() 為例:

復制代碼 代碼如下:

var app = require('express').createServer();

app.get('/', function(req, res){
  res.send('hello world');
});

app.listen(3000);

四、創(chuàng)建一個 HTTPS 服務器

如上述初始化一個 express.HTTPSServer 實例。然后我們給它傳一個配置對象,接受 key、cert 和其他在 https 文檔 所提到的(屬性/方法)。

復制代碼 代碼如下:

 var app = require('express').createServer({ key: ... });

五、配置

Express 支持任意環(huán)境,如產(chǎn)品階段(production)和開發(fā)階段(development)。開發(fā)者可以使用 configure() 方法來設置當前所需環(huán)境。如果 configure() 的調用不包含任何環(huán)境名,它將運行于所有環(huán)境中所指定的回調。

譯注: 像 production / development / stage 這些別名都是可以自已取的,如 application.js 中的 app.configure 所示。實際用法看下面例子。

下面這個例子僅在開發(fā)階段 dumpExceptions (拋錯),并返回堆棧異常。不過在兩個環(huán)境中我們都使用 methodOverride 和 bodyParser。注意一下 app.router 的使用,它可以(可選)用來加載(mount)程序的路由,另外首次調用 app.get()、app.post() 等也將會加載路由。

復制代碼 代碼如下:

app.configure(function(){
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(app.router);
});

app.configure('development', function(){
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  var oneYear = 31557600000;
  app.use(express.static(__dirname + '/public', { maxAge: oneYear }));
  app.use(express.errorHandler());
});


對于相似的環(huán)境你可以傳遞多個環(huán)境字符串:
復制代碼 代碼如下:

app.configure('stage', 'prod', function(){
  // config
});

對于任何內(nèi)部設置(#),Express 提供了 set(key[, val])、 enable(key) 和 disable(key) 方法:

譯注:設置詳見:application.js 的 app.set。

復制代碼 代碼如下:

 app.configure(function(){
    app.set('views', __dirname + '/views');
    app.set('views');
    // => "/absolute/path/to/views"

    app.enable('some feature');
    // 等價于:app.set('some feature', true);

    app.disable('some feature');
    // 等價于:app.set('some feature', false);

    app.enabled('some feature')
    // => false
 });


變更環(huán)境我們可以設置 NODE_ENV 環(huán)境變量,如:
復制代碼 代碼如下:

$ NODE_ENV=production node app.js

這非常重要,因為多數(shù)緩存機制只在產(chǎn)品階段是被打開的。

六、設置

Express 支持下列快捷(out of the box)設置:

1.basepath 用于 res.redirect() 的應用程序基本路徑(base path),顯式地處理綁定的應用程序(transparently handling mounted apps.)
2.view View 默認的根目錄為 CWD/views
3.view engine 默認 View 引擎處理(View 文件)并不需要使用后綴
4.view cache 啟用 View 緩存 (在產(chǎn)品階段被啟用)
5.charet 改變編碼,默認為 utf-8
6.case sensitive routes 路由中區(qū)分大小寫
7.strit routing 啟用后(路由中的)結尾 / 將不會被忽略(譯注:即 app.get('/sofish') 和 app.get('/sofish/') 將是不一樣的)
8.json callback 啟用 res.send() / res.json() 顯式的 jsonp 支持(transparent jsonp support)

七、路由

Express 利用 HTTP 動作提供一套提示性強、有表現(xiàn)力的路由 API。打個比方,如果想要處理某個路徑為 /user/12 的賬號,我們能像下面這樣來定義路由。關聯(lián)到命名占位符(named placeholders)的值可用 req.params 來訪問。

復制代碼 代碼如下:

app.get('/user/:id', function(req, res){
    res.send('user ' + req.params.id);
});

路由是一個在內(nèi)部被編譯為正則的字符串。譬如,當 /user/:id 被編譯,一個簡化版本的正則表達弄大概如下:
復制代碼 代碼如下:

// 修改一下官方的這個字符串
/\/user\/([^\/]+)\/?/

正則表達式可以傳入應用于復雜的場景。由于通過字面量正則表達式捕獲的內(nèi)容組是匿名的,我們可能直接通過 req.params 來訪問它們。因此,我們捕獲的第一組內(nèi)容將是 req.params[0],同時第二組是緊接著的 req.params[1]。
復制代碼 代碼如下:

app.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(req, res){
    res.send(req.params);
});

Curl 針對上述定義路由的請求:
復制代碼 代碼如下:

$ curl http://dev:3000/user
[null,null]
$ curl http://dev:3000/users
[null,null]
$ curl http://dev:3000/users/1
["1",null]
$ curl http://dev:3000/users/1..15
["1","15"]

下面是一些路由的實例,關聯(lián)到他們可能使用到的路徑:
復制代碼 代碼如下:

"/user/:id"
/user/12

"/users/:id?"
/users/5
/users

"/files/*"
/files/jquery.js
/files/javascripts/jquery.js

"/file/*.*"
/files/jquery.js
/files/javascripts/jquery.js

"/user/:id/:operation?"
/user/1
/user/1/edit

"/products.:format"
/products.json
/products.xml

"/products.:format?"
/products.json
/products.xml
/products

"/user/:id.:format?"
/user/12
/user/12.json


舉個例子,我們可以使用 POST 發(fā)送 json 數(shù)據(jù),通過 bodyParser 這個可以解析 json 請求內(nèi)容(或者其他內(nèi)容)的中間件來返回數(shù)據(jù),并將返回結果存于 req.body 中:
復制代碼 代碼如下:

var express = require('express')
  , app = express.createServer();

app.use(express.bodyParser());

app.post('/', function(req, res){
  res.send(req.body);
});

app.listen(3000);


通常我們可以使用一個像 user/:id 這樣,沒有(命名)限制的“傻瓜”式的占位符。然而比方說,我們要限制用戶 id 只能是數(shù)字,那么我們可能使用 /user/:id([0-9]+),這個將僅當占位符是包含至少一位數(shù)字時才生效(適配,match)。

八、進路控制(Passing Route Control)

我們可以通過調用第三個參數(shù),next() 函數(shù),來控制下一個適配的路由。如果找不到適配,控制權將會傳回給 Connect,同時中間件將會按在 use() 中添加的順序被依次調用。道理同樣適應于多個定義到同一路徑的路由,他們將會依次被調用直到其中某個不調用 next() 而決定做出請求響應。

復制代碼 代碼如下:

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next();
    }
});

app.get('/users', function(req, res){
    // do something else
});


app.all() 方法只調用一次就可以方便地把同樣的邏輯到所有 HTTP 動作。下面我們使用它來從偽數(shù)據(jù)中提取一個用戶,將其賦給 req.user。
復制代碼 代碼如下:

var express = require('express')
  , app = express.createServer();

var users = [{ name: 'tj' }];

app.all('/user/:id/:op?', function(req, res, next){
  req.user = users[req.params.id];
  if (req.user) {
    next();
  } else {
    next(new Error('cannot find user ' + req.params.id));
  }
});

app.get('/user/:id', function(req, res){
  res.send('viewing ' + req.user.name);
});

app.get('/user/:id/edit', function(req, res){
  res.send('editing ' + req.user.name);
});

app.put('/user/:id', function(req, res){
  res.send('updating ' + req.user.name);
});

app.get('*', function(req, res){
  res.send(404, 'what???');
});

app.listen(3000);


九、中間件

使用的 Connect 中間件(屬性)通常伴隨著你的一個常規(guī) Connect 服務器,被傳到 express.createServer() 。如:

復制代碼 代碼如下:

var express = require('express');

var app = express.createServer(
      express.logger()
    , express.bodyParser()
  );


另外,在 configure() 塊內(nèi) —— 這個漸進式的宮殿(譯注:笑^^,in a progressive manner),我們還可以方便地使用 use() 來添加中間件。
復制代碼 代碼如下:

app.use(express.logger({ format: ':method :url' }));

通常,使用 connect 中間件你可能會用到 require('connect'),像這樣:
復制代碼 代碼如下:

var connect = require('connect');
app.use(connect.logger());
app.use(connect.bodyParser());

這在某種程度上來說有點不爽,所以 express 重導出(re-exports)了這些中間件屬性,盡管他們是一樣的:
復制代碼 代碼如下:

app.use(express.logger());
app.use(express.bodyParser());

中間件的順序非常重要,當 Connect 收到一個請求,我們傳到 createServer() 或者 use() 執(zhí)行的第一個中間件將附帶三個參數(shù),request、response,以及一個回調函數(shù)(通常是 next)。當 next() 被調用,將輪到第二個中間件,依此類推。之所以說這是值得注意的,是因為很多中間件彼此依賴,例如 methodOverride() 查詢 req.body 方法來檢測 HTTP 方法重載,另一方面 bodyParser() 解析請求內(nèi)容并將其于寄存于 req.body。另一個例子是 cookie 解析和 session 支持,我們必須先 use() cookieParser() 緊接著 session()。

很多 Express 應用都包含這樣的一行 app.use(app.router),這看起來可能有點奇怪,其實它僅僅是一個包含所有定義路由規(guī)則,并執(zhí)行基于現(xiàn)有 URL 請求和 HTTP 方法路由查找的一個中間件功能。Express 允許你決定其位置(to position),不過默認情況下它被放置于底部。通過改變路由的位置,我們可以改變中間件的優(yōu)先級,譬如我們想把錯誤報告做為最后的中間件,以便任何傳給 next() 的異常都可以通過它來處理;又或者我們希望靜態(tài)文件服務優(yōu)先級更低,以允許我們的路由可以監(jiān)聽單個靜態(tài)文件請求的下載次數(shù),等等。這看起來差不多是這樣的:

復制代碼 代碼如下:

app.use(express.logger(...));
app.use(express.bodyParser(...));
app.use(express.cookieParser(...));
app.use(express.session(...));
app.use(app.router);
app.use(express.static(...));
app.use(express.errorHandler(...));

首先我們添加 logger(),它可能包含 node 的 req.end() 方法,提供我們響應時間的數(shù)據(jù)。接下來請求的內(nèi)容將會被解析(如果有數(shù)據(jù)的話),緊接著的是 cookie 解析和 session 支持,同時 req.session 將會在觸發(fā) app.router 中的路由時被定義,這時我們并不調用 next(),因此 static() 中間件將不會知道這個請求,如若已經(jīng)定義了如下一個路由,我們則可以記錄各種狀態(tài)、拒絕下載和消耗下載點數(shù)等。
復制代碼 代碼如下:

var downloads = {};

app.use(app.router);
app.use(express.static(__dirname + '/public'));

app.get('/*', function(req, res, next){
  var file = req.params[0];
  downloads[file] = downloads[file] || 0;
  downloads[file]++;
  next();
});

十、路由中間件

路由可以利用路由器中間件,傳遞一個以上的回調函數(shù)(或者數(shù)組)到其方法中。這個特性非常有利于限制訪問、通過路由下載數(shù)據(jù),等等。

通常異步數(shù)據(jù)檢索看起來可能像下例,我們使用 :id 參數(shù),嘗試加載一個用戶:

復制代碼 代碼如下:

app.get('/user/:id', function(req, res, next){
  loadUser(req.params.id, function(err, user){
    if (err) return next(err);
    res.send('Viewing user ' + user.name);
  });
});

為保證 DRY 原則和提升可讀,我們可以把這個邏輯應用于一個中間件內(nèi)。如下所示,抽象這個邏輯到中間件內(nèi)將允許你重用它,同時保證了我們路由的簡潔。
復制代碼 代碼如下:

function loadUser(req, res, next) {
  // You would fetch your user from the db
  var user = users[req.params.id];
  if (user) {
    req.user = user;
    next();
  } else {
    next(new Error('Failed to load user ' + req.params.id));
  }
}

app.get('/user/:id', loadUser, function(req, res){
  res.send('Viewing user ' + req.user.name);
});


多重路由可以,并按順序應用到更深一層的邏輯,如限制一個用戶賬號的訪問。下面的例子只允許通過鑒定的用戶才可以編輯他(她)的賬號。
復制代碼 代碼如下:

function andRestrictToSelf(req, res, next) {
  req.authenticatedUser.id == req.user.id
    ? next()
    : next(new Error('Unauthorized'));
}

app.get('/user/:id/edit', loadUser, andRestrictToSelf, function(req, res){
  res.send('Editing user ' + req.user.name);
});


時刻銘記路由只是簡單的函數(shù),如下所示,我們可以定義返回中間件的函數(shù)以創(chuàng)建一個更具表現(xiàn)力,更靈活的方案。
復制代碼 代碼如下:

function andRestrictTo(role) {
  return function(req, res, next) {
    req.authenticatedUser.role == role
      ? next()
      : next(new Error('Unauthorized'));
  }
}

app.del('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
  res.send('Deleted user ' + req.user.name);
});


常用的中間件“堆?!笨梢酝ㄟ^一個數(shù)組來傳遞(會被遞歸應用),這些中間件可以混著、匹配到任何層次(which can be mixed and matched to any degree)。
復制代碼 代碼如下:

var a = [middleware1, middleware2]
  , b = [middleware3, middleware4]
  , all = [a, b];

app.get('/foo', a, function(){});
app.get('/bar', a, function(){});

app.get('/', a, middleware3, middleware4, function(){});
app.get('/', a, b, function(){});
app.get('/', all, function(){});


對于這個實例的完整代碼,請看 route middleware example 這個倉庫。

我們可能會有多次想要“跳過”剩余的路由中間件,繼續(xù)匹配后續(xù)的路由。做到這點,我們只需調用 next() 時帶上 'route' 字符串 —— next('route')。如果沒有余下的路由匹配到請求的 URL,Express 將會返回 404 Not Found。

十一、HTTP 方法

至此已接觸了好幾次 app.get(),除此這外 Express 還提供了其他常見的 HTTP 動作,如 app.post() 、app.del() 等等。

POST 用法的一個常用例子是提交一個表單。下面我們簡單地在 html 中把表單的 method 屬性設置為 post,控制權將會指派給它下面所定義的路由。

復制代碼 代碼如下:

<form method="post" action="/">
     <input type="text" name="user[name]" />
     <input type="text" name="user[email]" />
     <input type="submit" value="Submit" />
</form>

默認上 Express 并不知道如何處理這個請求的內(nèi)容,因此我們必須添加 bodyParser 中間件,它將解析 application/x-www-form-urlencoded 和 application/json 請求的內(nèi)容,并把變量存放于 req.body 中。我們可以像下述示例一樣來使用這個中間件:
復制代碼 代碼如下:

app.use(express.bodyParser());

如下,我們的路由將有權訪問 req.body.user 對象,當有 name 和 email 被定義時它將包含這兩個屬性(譯注:如果表單發(fā)送的內(nèi)容不為空的話)。
復制代碼 代碼如下:

app.post('/', function(req, res){
  console.log(req.body.user);
  res.redirect('back');
});

當想在一個表單中使用像 PUT 這樣的方法,我們可以使用一個命名為 _method 的 hidden input,它可以用以修改 HTTP 方法。為了做這個,我們首先需要 methodOverride 中間件,它必須出現(xiàn)于 bodyParser 后面,以便使用它的 req.body中所包含的表單值。
復制代碼 代碼如下:

app.use(express.bodyParser());
app.use(express.methodOverride());

對于這些方法為何不是默認擁有,簡單來說只是因為它并不是 Express 所要求完整功能所必須。方法的使用依賴于你的應用,你可能并不需要它們,客戶端依然能使用像 PUT 和 DELETE 這樣的方法,你可以直接使用它們,因為 methodOverride 為 form 提供了一個非常不錯的解決方案。下面將示范如何使用 PUT 這個方法,看起來可能像:
復制代碼 代碼如下:

<form method="post" action="/">
  <input type="hidden" name="_method" value="put" />
  <input type="text" name="user[name]" />
  <input type="text" name="user[email]" />
  <input type="submit" value="Submit" />   
</form>

app.put('/', function(){
    console.log(req.body.user);
    res.redirect('back');
});

十二、錯誤處理

Express 提供了 app.error() 方法以便接收到的異常在一個路由里拋出,或者傳到 next(err) 中。下面這個例子將基于特定的 NotFound 異常處理不同的頁面:

復制代碼 代碼如下:

function NotFound(msg){
  this.name = 'NotFound';
  Error.call(this, msg);
  Error.captureStackTrace(this, arguments.callee);
}

NotFound.prototype.__proto__ = Error.prototype;

app.get('/404', function(req, res){
  throw new NotFound;
});

app.get('/500', function(req, res){
  throw new Error('keyboard cat!');
});


如下述,我們可以多次調用 app.error()。這里我們檢測 NotFound 的實例,并顯示 404 頁面,或者傳到 next 錯誤處理器。值得注意的是這些處理器可以在任何地方定義,因為他們將會在 listen() 的時候被放置于路由處理器下面。它允許在 configure() 塊內(nèi)有定義,以便我們能基于環(huán)境用不同的異常處理方式。
復制代碼 代碼如下:

app.error(function(err, req, res, next){
    if (err instanceof NotFound) {
        res.render('404.jade');
    } else {
        next(err);
    }
});

為求簡潔(for the simplicity),這里我們假定這個 demo 的所有錯誤為 500,當然你可以可以選擇自己喜歡的。像 node 執(zhí)行文件系統(tǒng)的系統(tǒng)調用時,你可能會接收到一個帶有 ENOENT 的 error.code,意思為 “不存在這樣的文件或目錄” 的錯誤,我們可以在錯誤處理器中使用,或者當有需要時可顯示一個指定的頁面。
復制代碼 代碼如下:

app.error(function(err, req, res){
  res.render('500.jade', {
     error: err
  });
});

我們的 app 同樣可以利用 Connect 的 errorHandler 中間件來匯報異常。譬如當我們希望在 “開發(fā)” 環(huán)境輸出 stderr 異常時,我們可以使用:
復制代碼 代碼如下:

app.use(express.errorHandler({ dumpExceptions: true }));

同時在開發(fā)階段我們可能需要在花哨的 HTML 頁面顯示我們傳遞和拋出的異常,對此我們可以把 showStack 設置為 true。
復制代碼 代碼如下:

app.use(express.errorHandler({ showStack: true, dumpExceptions: true }));

errorHandler 中間件還可以在 Accept: application/json 存在的時候返回 json,這對于開發(fā)重度依賴客戶端 Javascript 的應用非常有用。

十三、Route 參數(shù)預處理

路由參數(shù)預處理,通過隱式數(shù)據(jù)加載和請求驗證,可以大大提升你程序的可讀性。打個比方,你通常需要持續(xù)地從多個路由獲取基本數(shù)據(jù)。像用 /user/:id 加載一個用戶,通常來說我們可能會這樣干:

復制代碼 代碼如下:

app.get('/user/:userId', function(req, res, next){
  User.get(req.params.userId, function(err, user){
    if (err) return next(err);
    res.send('user ' + user.name);
  });
});

通過預處理,我們的參數(shù)可以映射到執(zhí)行驗證、控制(coercion),甚至從數(shù)據(jù)庫加載數(shù)據(jù)的回調。如下我們帶著參數(shù)名調用 app.param() 希望將其映射于某些中間件。如你所見,我們接受代表占位符值的 id 參數(shù)。使用這個,我們?nèi)绯<虞d用戶并處理錯誤,以及簡單地調用 next() 來把控制權交由下一個預處理或者路由處理器。
復制代碼 代碼如下:

app.param('userId', function(req, res, next, id){
  User.get(id, function(err, user){
    if (err) return next(err);
    if (!user) return next(new Error('failed to find user'));
    req.user = user;
    next();
  });
});

一旦這樣做,上所述將會大大地提升路由的可讀性,并且允許我們輕松地在整個程序中共享邏輯:
復制代碼 代碼如下:

app.get('/user/:userId', function(req, res){
  res.send('user ' + req.user.name);
});


十四、View 處理

View 文件件使用 <name>.<engine> 這樣的格式,其中 <engine> 是被 require 進來模塊的名。例如 layout.ejs 將告訴 view 系統(tǒng)去 require('ejs'),被加載的模塊必須(導出) exports.compile(str, options) 方法,并返回一個 Function 來適應 Express。app.register() 可用以改變這種默認行為,將文件擴展名映射到特定的引擎。譬如 “foo.html” 可以由 ejs 來處理。

下面這個例子使用 Jade 來處理 index.html。因為我們并未使用 layout: false,index.jade 處理后的內(nèi)容將會被傳入到 layout.jade 中一個名為 body 的本地變量。

復制代碼 代碼如下:

app.get('/', function(req, res){
    res.render('index.jade', { title: 'My Site' });
});

新的 view engine 設置允許我們指定默認的模板引擎,例如當我們使用 jade 時可以這樣設置:
復制代碼 代碼如下:

app.set('view engine', 'jade');

允許我們這樣處理:
復制代碼 代碼如下:

res.render('index');

對應于:
復制代碼 代碼如下:

res.render('index.jade');

當 view engine 被設定,擴展名實屬可選,但我們依然可以混著匹配模板引擎:
復制代碼 代碼如下:

res.render('another-page.ejs');

Express 同時還提供了 view options 設置,這將應用于一個 view 每次被渲染的時候,譬如你不希望使用 layouts 的時候可能會這樣做:
復制代碼 代碼如下:

app.set('view options', {
    layout: false
});

在需要的時候,這可以在 res.render() 調用的內(nèi)部進行重載:
復制代碼 代碼如下:

res.render('myview.ejs', { layout: true });

當有需要變更一個 layout,我們通常需要再指定一個路徑。譬如當我們已經(jīng)把 view engine 設置為 jade,并且這個文件命名為 ./views/mylayout.jade,我們可以這樣簡單地進行傳參:
復制代碼 代碼如下:

res.render('page', { layout: 'mylayout' });

否則(譯注:沒有把 view engine 設置為 jade 或者其他的引擎時),我們必須指定一個擴展名:
復制代碼 代碼如下:

res.render('page', { layout: 'mylayout.jade' });

它們同樣可以是絕對路徑:
復制代碼 代碼如下:

res.render('page', { layout: __dirname + '/../../mylayout.jade' });

對于這點有一個不錯的例子 —— 自定義 ejs 的起始和閉合標簽:
復制代碼 代碼如下:

app.set('view options', {
    open: '{{',
    close: '}}'
})

十五、View 部件

Express 的 view 系統(tǒng)內(nèi)置了部件(partials) 和集合器(collections)的支持,相當于用一個 “迷你” 的 view 替換一個文檔碎片(document fragment)。示例,在一個 view 中重復渲染來顯示評論,我們可以使用部件集:

復制代碼 代碼如下:

partial('comment', { collection: comments });

如果并不需要其他選項或者本地變量,我們可以省略整個對象,簡單地傳進一個數(shù)組,這與上述是等價的:
復制代碼 代碼如下:

partial('comment', comments);

在使用中,部件集無償?shù)靥峁┝艘恍?“神奇” 本地變量的支持:

1.firstInCollection true,當它是第一個對象的時候
2.indexInCollection 在集合器對象中的索引
3.lastInCollection true,當它是最后一個對象的時候
4.collectionLength 集合器對象的長度

本地變量的傳遞(生成)具備更高的優(yōu)先級,同時,傳到父級 view 的本地變量對于子級 view 同樣適應。例如當我們用 partial('blog/post', post) 來渲染一個博客文章,它將會生成一個 post 本地變量,在調用這個函數(shù)的 view 中存在本地變量 user,它將同樣對 blog/post 有效。(譯注:這里 partial 比較像 php 中的 include 方法)。

注意: 請謹慎使用部件集合器,渲染一個長度為 100 的部件集合數(shù)組相當于我們需要處理 100 個 view。對于簡單的集合,最好重復內(nèi)置,而非使用部件集合器以避免開銷過大。

十六、View 查找

View 查找相對于父級 view (路徑)執(zhí)行,如我們有一個 view 頁面叫作 views/user/list.jade,并且在其內(nèi)部寫有 partial('edit') 則它會嘗試加載 views/user/edit.jade,同理 partial('../messages') 將會加載 views/messages.jade。

View 系統(tǒng)還支持模板索引,允許你使用一個與 view 同名的目錄。例如在一個路由中,res.render('users') 得到的非 views/users.jade 即 views/users/index.jade。(譯注:先處理 <path>.<engine> 的情況,再處理 <path>/<index.<engine> 的情況,詳情可見 view.js。)

當使用上述 view 索引,我們在與 view 同一個目錄下,使用 partial('users') 中引用 views/users/index.jade,與此同時 view 系統(tǒng)會嘗試索引 ../users/index,而無須我們調用 partial('users')。

十七、Template Engines

下列為 Express 最常用的模板引擎:

1.Haml:haml 實現(xiàn)
2.Jade:haml.js 繼位者
3.EJS:嵌入式 JavaScript
4.CoffeeKup:基于 CoffeeScript 的模板
5.jQuery Templates

十八、Session 支持

Session 支持可以通過使用 Connect 的 session 中間件來獲得,為此通常我們同時需要在其前加上 cookieParser 中間件,它將解析和存儲 cookie 數(shù)據(jù)于 req.cookies 中。

復制代碼 代碼如下:

app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));

默認情況下 session 中間件使用 Connect 內(nèi)置的內(nèi)存存儲,然而還有其他多種實現(xiàn)方式。如 connect-redis 提供了一種 Redis 的 session 存儲,它這可像下面這樣被使用:
復制代碼 代碼如下:

var RedisStore = require('connect-redis')(express);
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat", store: new RedisStore }));

至此,req.session 和 req.sessionStore 屬性將可以被所有路由和后繼的中間件使用。在 req.session 上的所有屬性都會在一個響應中被自動保存下來,譬如當我們想要添加數(shù)據(jù)到購物車:
復制代碼 代碼如下:

var RedisStore = require('connect-redis')(express);
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat", store: new RedisStore }));

app.post('/add-to-cart', function(req, res){
  // 我們可能通過一個表單 POST 出多個 item
  // (在些使用 bodyParser() 中間件)
  var items = req.body.items;
  req.session.items = items;
  res.redirect('back');
});

app.get('/add-to-cart', function(req, res){
  // 當返回時,頁面 GET /add-to-cart
  // 我們可以檢查 req.session.items && req.session.items.length
  // 來打印出提示
  if (req.session.items && req.session.items.length) {
    req.notify('info', 'You have %s items in your cart', req.session.items.length);
  }
  res.render('shopping-cart');
});


對于 req.session 對旬,它還有像 Session#touch()、Session#destroy()、 Session#regenerate() 等用以維護和操作 session 的方法。更多的詳情請看 Connect Session 的文檔。

十九、升級指南

對于使用 Express 1.x 的同學,如果你有很重要的程序需要升級到 2.x 以獲得更好的支持,請看官方非常詳細的遷移指南http://expressjs.com/guide.html#migration-guide

相關文章

  • js實現(xiàn)圖片點擊左右輪播

    js實現(xiàn)圖片點擊左右輪播

    本文給大家分享的是使用javascript實現(xiàn)的圖片左右輪播的代碼,已經(jīng)封裝完畢,使用方法非常簡單,參考示例,有需要的小伙伴可以參考下。
    2015-07-07
  • 簡潔短小的 JavaScript IE 瀏覽器判定代碼

    簡潔短小的 JavaScript IE 瀏覽器判定代碼

    IE瀏覽器不管是什么版本,總是跟Web標準有些不太兼容。對于代碼工作者來說,自然是苦不堪言,為了考慮IE的兼容問題,不管是寫 CSS 還是 JS,往往都要對 IE 特別對待,這就少不了做些判斷。本文不討論如何區(qū)分 IE 的樣式,僅是 JS 判定 IE 瀏覽器。
    2010-03-03
  • 什么是JavaScript中的結果值?

    什么是JavaScript中的結果值?

    你知道JavaScript中的結果值是什么嗎?這篇文章主要介紹了JavaScript結果值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • JavaScript中的閉包介紹

    JavaScript中的閉包介紹

    這篇文章主要介紹了JavaScript中的閉包介紹,本文講解了Javacript 閉包、Javscript 閉包與this、Javscript 閉包與讀寫變量等內(nèi)容,需要的朋友可以參考下
    2015-03-03
  • uni-app配置APP自定義頂部標題欄設置方法與注意事項

    uni-app配置APP自定義頂部標題欄設置方法與注意事項

    相信很多小伙伴在使用uniapp進行多端開發(fā)的時候,在面對一些業(yè)務需求的時候,uniapp給我們提供的默認導航欄已經(jīng)不能滿足我們的業(yè)務需求了,這篇文章主要給大家介紹了關于uni-app配置APP自定義頂部標題欄設置方法與注意事項的相關資料,需要的朋友可以參考下
    2022-07-07
  • 微信小程序 數(shù)據(jù)緩存實現(xiàn)方法詳解

    微信小程序 數(shù)據(jù)緩存實現(xiàn)方法詳解

    這篇文章主要介紹了微信小程序 數(shù)據(jù)緩存實現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-08-08
  • javascript日期計算實例分析

    javascript日期計算實例分析

    這篇文章主要介紹了javascript日期計算,涉及javascript針對日期計算的相關技巧,這里需要注意索引的使用,需要的朋友可以參考下
    2015-06-06
  • js拼接字符串時如何在中間加上空格

    js拼接字符串時如何在中間加上空格

    這篇文章主要介紹了js拼接字符串時如何在中間加上空格的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 微信小程序頁面跳轉功能之從列表的item項跳轉到下一個頁面的方法

    微信小程序頁面跳轉功能之從列表的item項跳轉到下一個頁面的方法

    這篇文章主要介紹了微信小程序頁面跳轉功能之從列表的item項跳轉到下一個頁面的方法,結合具體實例形式總結分析了微信小程序頁面跳轉及列表item項跳轉頁面的相關操作技巧,需要的朋友可以參考下
    2017-11-11
  • 原生js滑動輪播封裝

    原生js滑動輪播封裝

    這篇文章主要為大家詳細介紹了原生js滑動輪播封裝,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07

最新評論