Express
是基於node.js
平臺的快速、開放、極簡的web
開放框架,它的地位與做用有點相似於前端的jquery
框架。它的英文官網地址爲 http://expressjs.com,其對應的中文官網地址爲 http://www.expressjs.com.cn 。下面來簡單介紹這個框架的用法。html
express
做爲一個第三方模塊包,一樣是經過npm
的方式進行下載,在當前的項目文件夾下,用命令-> npm install express
來完成下載。再經過 const express = require('express');
來完成引包。前端
當使用了express
這個模塊包以後,再也不須要引用node
的http
模塊,也能提供建立http
服務器的功能。其基本的代碼段結構爲:node
const express = require('express'); var app = express(); app.get('/',(req,res)=>{ res.send(''); }); app.listen(3000,'192.168.155.1');
引包以後返回一個函數體,將該函數體調用執行以後的返回值用app
來接收。app
相似於建立的那個http
服務器實例,該服務器監聽IP地址爲192.168.155.1
,端口號爲3000
。當瀏覽器以get
方式訪問http://192.168.155.1:3000/
時,調用執行該回調函數。其中res.send()
爲express
內部封裝的方法,在其內部能夠直接寫入返回的字符串參數,不用再用res.writeHead()
來設置狀態碼和mine
類型。jquery
該回調函數內部雖然能夠直接使用
express
本身封裝的res.send()
方法,不過原生的res.write()
與res.end()
方法仍然可使用。這三種方法內部參數默認填寫字符串類型,若是爲其餘類型的變量,須要使用.toString()
的方法先將其完成類型轉換。而且res.send()
與res.end()
均只能出現一次。web
上述代碼段當中的app.get('/',(req,res)=>{});
即爲一條路由選擇,表示當客戶端以get
方式訪問根目錄時,執行該回調函數當中的代碼。咱們能夠以這種方式進行路由選擇的設計,客戶端訪問服務器能夠有多種方式,如get
、post
、add
、delete
等,不過網頁端訪問通常只有get
與post
這兩種方式,其餘的方式通常由app
端發起。在瀏覽器端輸入網址、回車、刷新等方式均是默認以get
方式進行訪問。使用app.all()
方法則表明處理這個路由下的任何method
請求。express
url
當中的數據示例代碼段爲:npm
const express = require('express'); var app = express(); app.get('/:name/:age',(req,res)=>{ var a = req.params.name; var b = req.params.age; console.log(a); console.log(b); res.send(); }); app.listen(3000,'192.168.155.1');
則客戶端在訪問以後的返回結果爲:瀏覽器
url
地址當中不區分字母的大小寫以下所示的示例代碼:服務器
const express = require('express'); var app = express(); app.get('/ABb',(req,res)=>{ res.send('成功返回!') }); app.listen(3000,'192.168.155.1');
此時客戶端以get
方式訪問該網址時,不區分字母大小寫。app
url
地址當中全部get
方式提交的參數及錨點均會被忽略以下所示的示例代碼:
const express = require('express'); var app = express(); app.get('/a',(req,res)=>{ res.send('成功返回!') }); app.listen(3000,'192.168.155.1');
此時客戶端訪問爲http://192.168.155.1:3000/a#?name=qianqian&age=24
時,一樣與上述這條路由相匹配,執行其內部的回調函數。
當有客戶端訪問該服務器時,會根據用戶輸入的網址與咱們的路由設計的代碼進行路由匹配,一旦找到一個匹配的路由中間件以後,則執行其內部的回調函數,以後再也不與後面代碼當中出現的路由中間件進行路由匹配。以下所示的示例代碼:
const express = require('express'); var app = express(); app.get('/:username/:method',(req,res)=>{ console.log(1); res.end(); }); app.get('/admin/login',(req,res)=>{ console.log(2); res.end(); }) app.listen(3000,'192.168.155.1');
此時當客戶端訪問http://192.168.155.1:3000/admin/login
時,因爲先匹配上了第一個路由,執行內部的回調函數,再也不匹配第二個路由。
若是想讓其匹配上多條路由,則在上述的可能匹配上的路由的回調函數當中加入參數next
,並在回調函數體的最後加上next();
便可。示例代碼以下所示:
const express = require('express'); var app = express(); app.get('/:username/:method',(req,res,next)=>{ console.log(1); next(); }); app.get('/admin/login',(req,res)=>{ console.log(2); res.end(); }) app.listen(3000,'192.168.155.1');
此時當客戶端訪問http://192.168.155.1:3000/admin/login
時,因爲先匹配上了第一個路由,執行內部的回調函數,接下去再匹配第二個路由,而後執行其回調函數。
因爲
express
當中全部路由中間件的書寫順序相當重要,因此咱們在設計路由時,通常把具體的路由寫在上面,把抽象的路由寫在下面。
app.use()
是一個特殊的路由中間件咱們使用app.get()
或app.post()
等路由中間件進行路由設計時,咱們都是須要對客戶端輸入的網址進行精確的路由匹配的(最多隻能作到忽略url
當中的錨點即get
方式提交的參數數據)。但用app.use()
來進行路由設計時,咱們能夠把第一個參數的層級無限擴充下去。示例代碼以下所示:
const express = require('express'); var app = express(); app.use('/admin',(req,res)=>{ res.send('成功匹配!') }) app.listen(3000,'192.168.155.1');
此時當客戶端訪問http://192.168.155.1:3000/admin/new/path
時,也能匹配上這個路由,從而執行內部的回調函數。
此時咱們能夠在回調函數內部使用req.originalUrl
、req.baseUrl
、req.path
來獲得用戶輸入的網址當中的各個部分。示例代碼以下所示:
const express = require('express'); var app = express(); app.use('/admin',(req,res)=>{ console.log(req.originalUrl); console.log(req.baseUrl); console.log(req.path); res.send('成功匹配!') }) app.listen(3000,'192.168.155.1');
此時當客戶端訪問http://192.168.155.1:3000/admin/new/path
時,結果爲:
當咱們使用app.use()
這個路由中間件時,若是不寫網址或寫'/'
,則至關於與該指定ip
與指定端口號下的全部網址進行匹配,由於全部網址均可以看作時'/'
的擴展。app.use((req,res)=>{});
。咱們能夠在路由表的最後寫上app.use((req,res)=>{res.status(404).send('沒有這個頁面!');});
能夠作404頁面,當路由表當中全部路由都匹配不上時,則落入該路由項當中。咱們能夠用res.status(404).send('沒有這個頁面!');
這種方式設置指定的狀態碼。
相似於Apache
之類的傳統服務器軟件,都默認提供靜態服務,有web
容器和根目錄的概念。而對於Node.js
來講,沒有web
容器和根目錄的概念,因此當使用node.js
來呈遞頁面時,須要進行頂層路由設計,來把用戶訪問的url
地址和文件聯繫在一塊兒。但express
提供靜態文件的伺服能力。咱們能夠用app.use(express.static(target));
來指定用於提供靜態資源服務的文件夾,其中target
表示爲提供靜態資源服務的文件夾的絕對物理地址。
在主文件1.js
的同目錄下新建一個public
文件夾。示例代碼以下所示:
const express = require('express'); const path = require('path'); var target = path.join(__dirname,'./public'); var app = express(); app.use(express.static(target)); app.listen(3000,'192.168.155.1');
此時咱們在public
文件夾下新建一個index.html
頁面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h2>提供靜態資源服務文件夾當中的首頁頁面!</h2> </body> </html>
此時public
文件夾爲提供靜態資源服務的文件夾,當用戶端訪問http://192.168.155.1:3000
時,默認進入public
文件夾,顯示該文件夾當中的index.html
頁面。
咱們也能夠在app.use()
方法當中加上第一個參數,如app.use('/static',express.static(target));
此時用戶須要輸入http://192.168.155.1:3000/static
時,纔會至關於進入public
文件夾,顯示該文件夾當中的index.html
頁面。
咱們通常把提供靜態資源服務的路由代碼寫在上面,防止咱們在進行路由表設計時,與現有的路由發生衝突。
這裏主要介紹express
與後臺模板引擎ejs
的配合能力。咱們將ejs
下載到項目文件夾的node_modules
文件夾當中,在主文件1.js
當中再也不須要使用require
的方式進行引入。只要寫app.set("view engine","ejs");
則完成了引包的工做。接下去再在當前目錄下新建一個固定文件名爲views
的文件夾,把渲染的html
頁面放在其中,後綴名改成.ejs
。用res.render("文件名",{數據});
咱們在與主文件1.js
的同目錄下新建一個views
文件夾,裏面新建一個index.ejs
的文件,內部代碼爲:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h2>後臺模板引擎:<%= a %></h2> <ul> <% for(var i = 0; i < list.length; i++){ %> <li><%= list[i] %></li> <% } %> </ul> </body> </html>
其中主文件1.js
的示例代碼爲:
const express = require('express'); var app = express(); app.set("view engine","ejs"); app.get('/',(req,res)=>{ res.render("index",{ a:'ejs', list:['apple','banana','pear','tomato'] }) }) app.listen(3000,'192.168.155.1');
此時結果爲:
若是咱們不想使用views文件夾,咱們能夠經過
app.set("views","abc");
命令更改默認文件夾的名字。
get
請求的參數在url
當中,在express
當中,再也不須要使用url
模塊,直接使用req.query
便可獲得客戶端經過get
請求發送的參數對象。示例代碼以下所示:
const express = require('express'); var app = express(); app.get('/',(req,res)=>{ console.log(req.query); res.send('成功!'); }); app.listen(3000,'192.168.155.1');
post
請求在express
當中不能直接得到,須要使用第三方模塊包body-parser
。經過npm
的方式完成模塊包的下載以後,經常使用的代碼爲const bodyParser = require('body-parser');app.use(bodyParser.urlencoded({extended:false}));
,以後便可使用req.body
來獲得參數對象。
咱們在views
文件夾當中寫下一個form.ejs
表單,示例代碼以下所示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <form action="http://192.168.155.1:3000" method="POST"> <p>姓名:<input type="text" name="name"></p> <p>年齡:<input type="text" name="age"></p> <p><input type="submit" value="提交"></p> </form> </body> </html>
其中主文件1.js
的示例代碼爲:
const express = require('express'); const bodyParser = require('body-parser'); var app = express(); app.set('view engine','ejs'); app.use(bodyParser.urlencoded({extended:false})); app.get('/',(req,res)=>{ res.render('form'); }); app.post('/',(req,res)=>{ console.log(req.body); res.send('表單提交成功!'); }); app.listen(3000,'192.168.155.1');
此時在啓動在服務器以後,客戶端輸入網址http://192.168.155.1:3000
時,呈遞該表單:
當完成表單填寫,並提交以後,結果爲:
這樣就實現了一個post
方式表單提交的功能。
body-parser
是一個輕量級的模塊包,僅僅適合處理表單內容的提交,但不能處理文件、圖片等多媒體文件的提交。若是客戶端提交的表單當中包含文件、圖片等,仍是建議使用formidable
模塊包進行處理。