-
個(gè)人入門(mén)學(xué)習(xí)用筆記、不過(guò)多作為參考依據(jù)。如有錯(cuò)誤歡迎斧正
-
Express框架
- Express在后臺(tái)的受歡迎程度與jQuery一樣、是企業(yè)標(biāo)準(zhǔn).
- http://www.expressjs.com.cn/
- http://www.expressjs.com/
-
路由能力
const express = require('express'); const app = express(); //get請(qǐng)求的響應(yīng) app.get('/',(req,res) => { res.send('你好'); }); //post請(qǐng)求的響應(yīng) app.post('/haha',(req,res) => { res.send('這是haha'); }); //所有請(qǐng)求 app.all('/',(req,res) => { res.send('你好'); }); //支持正則表達(dá)式(內(nèi)部表示參數(shù)區(qū)分) app.get(/^\/student\/([\d]{10})$/,(req,res) =>{ res.send('學(xué)生信息.學(xué)號(hào):'+req.params[0]); }); //:xxxx可以自定義參數(shù)通過(guò).req.params.xxxx提取 app.get('/teacher/:gonghao',(req,res) => { var gonghao; gonghao = req.params.gonghao; res.send('老師信息.工號(hào):'+gonghao); }); app.listen(3000,() =>{ console.log('監(jiān)聽(tīng)成功'); });
-
與模板引擎配合
與原生ejs相比、不需要fs讀取文件、轉(zhuǎn)成字符串、再進(jìn)行替換輸出
const express = require('express'); const app = express(); //此處就相當(dāng)于引用了ejs app.set('view engine','ejs'); app.get('/',(req,res) => { var json = { 'news':['第一個(gè)','第二個(gè)','第三個(gè)'] } //在工程內(nèi)存在ejs框架的情況下、并不需要引用ejs即可使用模板 //默認(rèn)讀取文件的路徑為./views/xxx。可以直接簡(jiǎn)寫(xiě)成xxx //講haha.ejs文件與json模板配合后、返回替換成功的文件。 res.render('haha',json); }); app.listen(3000);
-
RESTful路由設(shè)計(jì)
- 讓get、add、post、delete響應(yīng)同一個(gè)url的不同http請(qǐng)求方式。節(jié)約url數(shù)量
- html通常只發(fā)起get、post。app可能會(huì)出現(xiàn)add、delete請(qǐng)求。
const express = require('express'); const app = express(); //設(shè)置模板引擎 app.set('view engine','ejs'); app.get('/',(req,res)=>{ //直接返回form.ejs解析成html后的文件 res.render('form'); }); //post和get共用一個(gè)url //節(jié)約了一個(gè)url app.post('/',(req,res) =>{ res.send('成功'); }); app.listen(3000);
-
中間件
get、post、use等、叫做中間件
中間件執(zhí)行的順序。
自上而下、當(dāng)?shù)谝粋€(gè)路徑匹配成功、默認(rèn)不繼續(xù)尋找(即使第一個(gè)中并沒(méi)有send())。
但我們可以通過(guò)調(diào)用第三個(gè)參數(shù)next()、讓app繼續(xù)向下搜索響應(yīng)。需要注意的是next當(dāng)前函數(shù)下不能以再使用send();
const express = require('express'); const app = express(); //正常情況下、'/:Id'已經(jīng)包含了'/100'所以路由搜索到此為止。 app.get('/:Id',(req,res,next) => { console.log('第一個(gè)get'); //通過(guò)next、讓app繼續(xù)向下搜索 next(); }); app.get('/100',(req,res) => { console.log('第二個(gè)get'); res.send() }); app.listen(3000);
use
use也是一個(gè)中間件。
use就是get與post
與get/post不同。他可以匹配目標(biāo)路徑之后所有的子文件夾。
此示例下、admin/aa/xxx/x/x/x/x/x/是可以被檢索的。
但是admin/bb則不行const express = require('express'); const app = express(); app.use('/admin/aa', function(req, res, next) { // GET 'http://www.example.com/admin/aa/new' console.log(req.originalUrl); // '/admin/aa/new' console.log(req.baseUrl); // '/admin/aa' console.log(req.path); // '/new' next(); }); //當(dāng)不實(shí)現(xiàn)具體路徑的時(shí)候、express會(huì)自動(dòng)匹配所有地址 app.use((req,res) => { res.send('你好'); }); app.listen(3000);
靜態(tài)文件伺服
// 靜態(tài)文件伺服 const express = require('express'); const app = express(); //所有請(qǐng)求全部先檢測(cè)靜態(tài)文件 app.use(express.static('./public')); //只有以/wocao開(kāi)頭的采取讀取靜態(tài)文件 app.use('/wocao',express.static('./wocao')); app.get('/hahaha',(req,res) => { res.send('hahaha') }); app.listen(3000);
此時(shí)在瀏覽器中輸入127.0.0.1:3000/xxx.html即可
輸入127.0.0.1:3000/wocao/xxx.html也可
輸入127.0.0.1:3000/hahaha 顯示hahaha(static內(nèi)部有next()機(jī)制)
輸入其他顯示cannot get
在讀取靜態(tài)文件的情況下、如果只輸入文件夾名。會(huì)默認(rèn)讀取該文件夾下的index.html文件
404
把通配符放于最后處理。這樣沒(méi)有經(jīng)過(guò)路由的所有頁(yè)面默認(rèn)由 404.html 來(lái)接管。
// 404 app.get('*', function(req, res){ res.render('404.html', { title: 'No Found' }) });
內(nèi)容渲染
大多數(shù)情況下、渲染用res.render()。將會(huì)根據(jù)views中的模板文件進(jìn)行渲染。
如果不想使用views文件夾(比如替換成view2文件夾)
app.set('views','views2'); //也可以跨路徑指定(比如指定到上級(jí)的views) app.set('views','../views');
如果想寫(xiě)一個(gè)快速測(cè)試頁(yè)、當(dāng)然可以使用res.send()。這個(gè)函數(shù)將根據(jù)內(nèi)容、自動(dòng)幫我們?cè)O(shè)置Content-Type頭部和200狀態(tài)碼。
send同end一樣只能用一次。
一般send用于返回json等數(shù)據(jù)。如果想使用不同的狀態(tài)碼,可以
res.status(404).send('sorry,web caonnot find that!');
如果想使用不同的Content-Type,可以
res.set('Content-Type','text/html');
Get請(qǐng)求處理
express會(huì)自動(dòng)幫我們把參數(shù)轉(zhuǎn)換成json以及數(shù)組.通過(guò)req.query得到
const express = require('express'); const app = express(); app.get('*',(req,res) =>{ console.log(req.query); res.send(req.query); }); app.listen(3000);
Post請(qǐng)求
文檔推薦使用req.body也就是 body-parse來(lái)處理
const express = require('express'); const app = express(); var bodyParser = require('body-parser'); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.set('view engine','ejs'); app.set('views','../views'); app.get('*',(req,res) =>{ res.render('form'); }); app.post('/',(req,res) => { console.log(req.body); res.send(req.body); }); app.listen(3000);
如果涉及文件上傳、依舊需要使用formidable
res.sendFile
如果你想直接返回一個(gè)文件、比如html。但又不想耽誤用render傳輸模板文件、可以使用這個(gè)
app.get('/test',(req,res) => { res.sendFile(__dirname +'/views/index.html'); });
頁(yè)面綁定參數(shù)
ejs本身就是替換模板、所以:
//最后的404中間件 app.use('*',(req,res) => { res.render('err',{'kirito':'kirito111'}); }); <script> var kirito ='<%= kirito%>'; console.log(kirito) </script>
重定向
定向回上一頁(yè)
res.redirect('/');
定向到其他路由
res.redirect('/xxx');
Cookie
- HTTP是無(wú)狀態(tài)協(xié)議。也就是說(shuō)當(dāng)你瀏覽了一個(gè)頁(yè)面、然后轉(zhuǎn)到同一個(gè)網(wǎng)站的另一個(gè)頁(yè)面、服務(wù)器無(wú)法認(rèn)識(shí)到、這是同一臺(tái)計(jì)算機(jī)、同一個(gè)瀏覽器。
- Cookie是一個(gè)簡(jiǎn)單的想法:當(dāng)訪問(wèn)一個(gè)頁(yè)面的時(shí)候、服務(wù)器在下行HTTP報(bào)文中、命令瀏覽器儲(chǔ)存一個(gè)字符串;瀏覽器再訪問(wèn)同一個(gè)域的時(shí)候、將把這個(gè)字符串?dāng)y帶到上行HTTP請(qǐng)求中。
特點(diǎn):
- 不加密、用戶可以看到
- 用戶可以刪除、或者禁用
- cookie可以被篡改
- cookie可以用于攻擊
- cookie的存儲(chǔ)量很小。未來(lái)或許要被localstorage(IE9兼容)取代
express中的Cookie
res負(fù)責(zé)設(shè)置cookie
res.cookie(K&V)
req負(fù)責(zé)識(shí)別cookie
通過(guò)node設(shè)置cookie
res.cookie.key const express = require ('express'); const app = express(); //使用cookie必須使用cookie-parser中間件 const cookieParser = require('cookie-parser'); app.use(cookieParser()); app.get('/',(req,res) => { //maxAge在express中以毫秒為單位 res.cookie('xihao','tfboys',{maxAge:900000,httpOnly:true}); res.send('cookie='+req.cookies.xihao); }); app.listen(3000);
下行報(bào)文中
WechatIMG60.jpeg
- 上行報(bào)文中
WechatIMG61.jpeg
Session
保持登錄狀態(tài)
Session從頭至尾依賴(lài)cookie、一旦禁用/清除cookie、sessiion也會(huì)失效
Session作為亂碼令牌發(fā)還給用戶。服務(wù)器為令牌存儲(chǔ)具體信息
理論上可以存儲(chǔ)無(wú)線大小的數(shù)據(jù)
const express = require ('express'); const app = express(); var session = require('express-session'); app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true })); app.get('/login',(req,res) => { //設(shè)置session req.session.login = '1'; req.session.username = 'kirito'; res.send('成功登錄'); }); app.get('/',(req,res) => { if (req.session.login == '1'){ res.send('歡迎'+req.session.username+'您已成功登錄'); }else { res.send('尚未登錄'); } }); app.listen(3000);
需要注意的是
若將服務(wù)器重新啟動(dòng)、訪問(wèn)根目錄。會(huì)顯示未登錄狀態(tài)
因?yàn)閘ogin以及username都緩存在服務(wù)器的express-session模塊內(nèi)