Express實用技巧和設計模式

1.Express介紹

Express是一個簡介、靈活的node.js web應用開發框架,是目前最流行的基於node.js的web開發框架,提供了一系列強大的功能,好比:css

  • 路由控制
  • 中間件
  • 靜態文件服務
  • 模板解析

本文主要介紹這些功能的使用和它的設計理念html

2.Express如何使用

本地安裝node

$ npm install express
複製代碼

獲取、引用經過變量app(app其實在內部是application返回的一個handle函數,全部express的方法都在app上的原型方法) 咱們能夠調用express的方法linux

var express = require('express)
var app = express()
app.liten(3000)
複製代碼

3.路由控制

express經過匹配請求路徑,在作request、response操做,具體看下面get、post方法git

  • Express的get方法github

    第一個參數path爲請求路徑,第二個參數爲處理請求的回調函數web

    app.get(path, function(req, res))
    複製代碼

    get方法使用express

    const express = require('express');
    const app = express();
    //匹配htp://localhost:3000/hello作相關req,res的操做
    app.get('/hello',function(req,res){
        res.end('hello');
    });
    //匹配htp://localhost:3000/world作相關req,res的操做
    app.get('/world',function(req,res){
        res.end('world');
    });
    //匹配全部,主要用做not found
    app.get('*',function(req,res){
        res.setHeader('Content-Type','text/plain;charset=utf8');
        res.end('Not Found');
    });
    app.listen(3000);
    複製代碼
  • Express的post方法npm

    第一個參數path爲請求路徑,第二個參數爲處理請求的回調函數和get同樣設計模式

    app.post(path,function(req,res))
    複製代碼

    post方法使用

    var express = require('./express');
    var app = express();
    //匹配htp://localhost:3000/hello作相關req,res的操做
    app.post('/hello', function (req,res) {
       res.end('hello');
    });
    //匹配全部,主要用做not found
    app.post('*', function (req,res) {
        res.end('post沒找到');
    });
    app.listen(3000);
    複製代碼

    經過linux命令發送post請求

    $ curl -X POST http://localhost:3000/hello
    複製代碼
  • Express的all方法

    監聽全部的請求方法,能夠匹配全部的HTTP動詞。根據請求路徑來處理客戶端發出的全部請求,參數同上

    app.all(path,function(req, res))
    複製代碼

    all方法使用

    const express = require('express');
    const app = express();
    app.all('/world',function(req,res){
        res.end('all world');
    });
    app.listen(3000);
    複製代碼
  • Express Router的設計理念

    先看以下代碼

    const express = require('express');
    const app = express();
    app.get('/user',function(req,res,next){
        console.log(1);
        next();
    },function(req,res,next){
        console.log(11);
        next();
    }).get('/world',function(req,res,next){
        console.log(2);
        next();
    }).get('/hello',function(req,res,next){
        console.log(3);
        res.end('ok');
    });
    app.listen(3000);
    複製代碼

    如上代碼,體現出express router的一個概念,就是二維數組的二維數據形式,這個概念的主要意義是:在router路由容器中存放一層層route實例,而且每層route實例中存放一層層callback,當匹配上一個route的時候,執行它裏面的callback

    以下圖所示

express-router

再router和route中分別用stack存儲,不一樣的是Router中的stack存放的是Route,而且根據相同路由匹配,遍歷Stack中相關Route,其中handle方法是掛載到layer上面的Route,而且觸發Route從而遍歷Route中的Stack,在Route中的Stack存放的是一層層的callback,因此最終調用全部callback在同一個匹配路徑上,其中核心原理就是這個二維數組的二維數據形式

4.中間件

中間件就是處理HTTP請求的函數,用來完成各類特定的任務,好比檢查用戶是否登陸、檢測用戶是否有權限訪問等,它的特色是:

  • 一箇中間件處理完請求和響應能夠把相應數據再傳遞給下一個中間件

  • 回調函數的next參數,表示接受其餘中間件的調用,函數體中的next(),表示將請求數據繼續傳遞

  • 能夠根據路徑來區分返回執行不一樣的中間件

  • 1.中間件的使用

    主要經過use方法

    var express = require('express');
    var app = express();
    app.use(function (req,res,next) {
        console.log('所有匹配');
        next();
    });
    app.use('/water', function (req,res,next) {
        console.log('只匹配/water');
        next();
    });
    app.get('/water', function (req,res) {
        res.end('water');
    });
    app.listen(3000);
    複製代碼

    2.中間件原理

    經過Application原型上的use方法,將Router變函數,抽象出Router方法複用,Router處理中間件,其實就是上面所講述的路由控制原理,看以下代碼,能夠用app下面的use方法調取中間件,也能夠建立一個express.router,在經過app下面use調用這個中間件,造成一個父子級別的中間件路由,下面user.use就是當訪問/user/或者/user/2的子路由

    const express = require('../');
    const app = express();
    app.use(function(req,res,next){
        console.log('Ware1:',Date.now());
        next('wrong');
    });
    app.get('/',function(req,res,next){
        res.end('1');
    });
    const user = express.Router();
    user.use(function(req,res,next){
        console.log('Ware2',Date.now());
        next();
    });
    user.use('/2',function(req,res,next){
        res.end('2');
    });
    app.use('/user',user);
    app.use(function(err,req,res,next){
        res.end('catch '+err);
    });
    app.listen(3000,function(){
        console.log('server started at port 3000');
    });
    複製代碼

    3.中間件設計模式

    主要思想就是Application有一個router屬性指向了Router函數,在Router中返回一個router函數,將get/handle等方法掛載到返回的router上面,其實express.Router()方法就是Router函數。而且中間件和普通的路由都是在Router的stack中,如圖所示

express-use

5.靜態服務文件

若是要在網頁中加載靜態文件(css、js、img),就須要另外指定一個存放靜態文件的目錄,當瀏覽器發出非HTML文件請求時,服務器端就會到這個目錄下去尋找相關文件

var express = require('express');
var app = express();
var path = require('path');
app.use(express.static(path.join(__dirname,'public')));
app.listen(3000);
複製代碼
  • 靜態文件服務器實現

    static屬於express內置中間件,其中原理主要是調用了serve-static庫,具體實現是原生node.js API,能夠查看我寫的一篇如何搭建靜態服務器 static-server

6.模板解析

這裏主要說的是ejs模板,具體API請查閱 EJS官網

  • 安裝ejs

    $ npm install ejs
    複製代碼
  • 設置模板

    var express = require('express');
    var path = require('path');
    var app = express();
    app.set('view engine','ejs');
    app.set('views',path.join(__dirname,'views'));
    app.listen(3000);
    複製代碼
  • 渲染html

    app.set('view engine','html')
    app.set('views',path.join(__dirname,'views'));
    app.engine('html',require('ejs').__express);
    複製代碼
  • 渲染視圖

    • 第一個參數 要渲染的模板
    • 第二個參數 渲染所須要的數據
    app.get('/', function (req,res) {
        res.render('hello',{title:'hello'},function(err,data){});
    });
    複製代碼
  • 模板的實現

    res.render = function (name, data) {
        var viewEngine = engine.viewEngineList[engine.viewType];
        if (viewEngine) {
            viewEngine(path.join(engine.viewsPath, name + '.' + engine.viewType), data, function (err, data) {
                if (err) {
                    res.status(500).sendHeader().send('view engine failure' + err);
                } else {
                    res.status(200).contentType('text/html').sendHeader().send(data);
                }
            });
        } else {
            res.status(500).sendHeader().send('view engine failure');
        }
    }
    複製代碼

7.結語

本篇文章主要介紹核心功能和核心代碼思想,其他的方法如:redirect(重定向)、body-parser(請求體解析)、send方法等等不作介紹,具體請查閱下方給出的相關教程

8.博客

魏燃技術博客

有任何問題可留言或者發送本人郵箱ngaiwe@126.com

相關文章
相關標籤/搜索