暫存

Twitch 商城網(wǎng)站

介紹:

1、Node.js搭建的網(wǎng)站,采用Mongodb數(shù)據(jù)庫(kù)
2缺谴、后臺(tái)框架 借用了 express 窗骑,模板引擎使用的 ejs女责,對(duì)于數(shù)據(jù)庫(kù)的操作使用的是 mongoose

網(wǎng)站搭建流程


入口文件 app.js

我們來(lái)作一些修改,以上代碼實(shí)現(xiàn)了路由的功能创译,我們當(dāng)然可以不要 routes/index.js 文件抵知,把實(shí)現(xiàn)路由功能的代碼都放在 app.js 里,但隨著時(shí)間的推移 app.js 會(huì)變得臃腫難以維護(hù),這也違背了代碼模塊化的思想刷喜,所以我們把實(shí)現(xiàn)路由功能的代碼都放在 routes/index.js 里残制。官方給出的寫(xiě)法是在 app.js 中實(shí)現(xiàn)了簡(jiǎn)單的路由分配,然后再去 index.js 中找到對(duì)應(yīng)的路由函數(shù)掖疮,最終實(shí)現(xiàn)路由功能初茶。我們不妨把路由控制器和實(shí)現(xiàn)路由功能的函數(shù)都放到 index.js 里,app.js 中只有一個(gè)總的路由接口浊闪。

    var routes = require('./routes/index');
    //在執(zhí)行到錯(cuò)誤處理程序前 將 express實(shí)例 app 傳給 路由
    routes(app);

routes/index.js 文件纺蛆,總的路由接口

    module.exports = function(app) {
      app.get('/', function (req, res) {
        res.render('index', { title: 'Express' });
      });
    };

app.js 和 index.js 修改成這樣就達(dá)成了總路由接口的配置了!

路由規(guī)則

express 封裝了多種 http 請(qǐng)求方式规揪,我們主要只使用 get 和 post 兩種桥氏,即 app.get() 和 app.post()
app.get() 和 app.post() 的第一個(gè)參數(shù)都為請(qǐng)求的路徑,第二個(gè)參數(shù)為處理請(qǐng)求的回調(diào)函數(shù)猛铅,回調(diào)函數(shù)有兩個(gè)參數(shù)分別是 req 和 res字支,代表請(qǐng)求信息和響應(yīng)信息 。路徑請(qǐng)求及對(duì)應(yīng)的獲取路徑有以下幾種形式:這里就參考文檔

解析 :

  • req.query: 處理 get 請(qǐng)求奸忽,獲取 get 請(qǐng)求參數(shù)
  • req.params: 處理 /:xxx 形式的 get 或 post 請(qǐng)求堕伪,獲取請(qǐng)求參數(shù)
  • req.body: 處理 post 請(qǐng)求,獲取 post 請(qǐng)求體
  • req.param(): 處理 get 和 post 請(qǐng)求栗菜,但查找優(yōu)先級(jí)由高到低為 req.params→req.body→req.query

路徑規(guī)則還支持正則表達(dá)式欠雌,更多請(qǐng)查閱 Express 官方文檔

接下來(lái)自己添加一個(gè)路由規(guī)則做下測(cè)試吧疙筹!

模板引擎


什么是模板引擎

模板引擎(Template Engine)是一個(gè)將頁(yè)面模板和要顯示的數(shù)據(jù)結(jié)合起來(lái)生成 HTML 頁(yè)面的工具富俄。
如果說(shuō)上面講到的 express 中的路由控制方法相當(dāng)于 MVC 中的控制器的話,那模板引擎就相當(dāng)于 MVC 中的視圖而咆。

什么事ejs霍比?

ejs 是模板引擎的一種,也是我們這個(gè)教程中使用的模板引擎暴备,因?yàn)樗褂闷饋?lái)十分簡(jiǎn)單悠瞬,而且與 express 集成良好。

使用模板引擎

前面我們通過(guò)以下兩行代碼設(shè)置了模板文件的存儲(chǔ)位置和使用的模板引擎:

app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

注意:我們通過(guò) express -e blog 只是初始化了一個(gè)使用 ejs 模板引擎的工程而已涯捻,比如 node_modules 下添加了 ejs 模塊浅妆,views 文件夾下有 index.ejs 。并不是說(shuō)強(qiáng)制該工程只能使用 ejs 不能使用其他的模板引擎比如 jade障癌,真正指定使用哪個(gè)模板引擎的是 app.set('view engine', 'ejs'); 凌外。

在 routes/index.js 中通過(guò)調(diào)用 res.render() 渲染模版,并將其產(chǎn)生的頁(yè)面直接返回給客戶端混弥。它接受兩個(gè)參數(shù)趴乡,第一個(gè)是模板的名稱,即 views 目錄下的模板文件名蝗拿,擴(kuò)展名 .ejs 可選晾捏。第二個(gè)參數(shù)是傳遞給模板的數(shù)據(jù)對(duì)象,用于模板翻譯哀托。

當(dāng)我們 res.render('index', { title: 'Express' }); 時(shí)惦辛,模板引擎會(huì)把 <%= title %> 替換成 Express,然后把替換后的頁(yè)面顯示給用戶仓手。

注意:我們通過(guò) app.use(express.static(path.join(__dirname, 'public'))) 設(shè)置了靜態(tài)文件目錄為 public 文件夾胖齐,所以上面代碼中的 href='/stylesheets/style.css' 就相當(dāng)于 href='public/stylesheets/style.css'

ejs 的標(biāo)簽系統(tǒng)非常簡(jiǎn)單,它只有以下三種標(biāo)簽:

  • <% code %>:JavaScript 代碼嗽冒。
  • <%= code %>:顯示替換過(guò) HTML 特殊字符的內(nèi)容呀伙。
  • <%- code %>:顯示原始 HTML 內(nèi)容舅世。

注意: <%= code %> 和 <%- code %> 的區(qū)別日丹,當(dāng)變量 code 為普通字符串時(shí),兩者沒(méi)有區(qū)別逛钻。當(dāng) code 比如為 <h1>hello</h1> 這種字符串時(shí)贬蛙,<%= code %> 會(huì)原樣輸出 <h1>hello</h1>雨女,而 <%- code %> 則會(huì)顯示 H1 大的 hello 字符串。

我們可以在 <% %> 內(nèi)使用 JavaScript 代碼阳准。下面是 ejs 的官方示例:

The Data

supplies: ['mop', 'broom', 'duster']

The Template

<ul>
<% for(var i=0; i<supplies.length; i++) {%>
   <li><%= supplies[i] %></li>
<% } %>
</ul>   

The Result

<ul>
  <li>mop</li>
  <li>broom</li>
  <li>duster</li>
</ul>

我們可以用上述三種標(biāo)簽實(shí)現(xiàn)頁(yè)面模板系統(tǒng)能實(shí)現(xiàn)的任何內(nèi)容氛堕。

頁(yè)面布局

這里我們不使用layout進(jìn)行頁(yè)面布局,而是使用更為簡(jiǎn)單靈活的include野蝇。include 的簡(jiǎn)單使用如下:

index.ejs

<%- include a %>
hello,world!
<%- include b %>

a.ejs

this is a.ejs

b.ejs

this is b.ejs

最終index.ejs會(huì)顯示

this is a.ejs
hello,world!
this is b.ejs

根據(jù)上面讼稚,我們具體初步的了解了一些nodejs、express一些特性绕沈,接下來(lái)正式開(kāi)始搭建多人博客乱灵。


搭建多人博客


功能分析

搭建一個(gè)簡(jiǎn)單的具有多人注冊(cè)、登錄七冲、發(fā)表文章痛倚、登出功能的博客。

設(shè)計(jì)目標(biāo)

未登錄:主頁(yè)左側(cè)導(dǎo)航顯示 home澜躺、login蝉稳、register,右側(cè)顯示已發(fā)表的文章掘鄙、發(fā)表日期及作者耘戚。
登陸后:主頁(yè)左側(cè)導(dǎo)航顯示 home、post操漠、logout收津,右側(cè)顯示已發(fā)表的文章饿这、發(fā)表日期及作者。
用戶登錄撞秋、注冊(cè)长捧、發(fā)表成功以及登出后都返回到主頁(yè)。

未登錄效果圖:
主頁(yè):

未登錄主頁(yè)

登錄頁(yè):


登錄頁(yè)
登錄頁(yè)

注冊(cè)頁(yè):


注冊(cè)頁(yè)
注冊(cè)頁(yè)

登錄后的效果圖:
主頁(yè):

主頁(yè)
主頁(yè)

發(fā)表頁(yè):


發(fā)表頁(yè)
發(fā)表頁(yè)

注意:沒(méi)有登出頁(yè)吻贿,當(dāng)點(diǎn)擊 LOGOUT 后串结,退出登陸并返回到主頁(yè)。

路由規(guī)劃

我們已經(jīng)把設(shè)計(jì)的構(gòu)想圖貼出來(lái)了舅列,接下來(lái)的任務(wù)就是完成路由規(guī)劃了肌割。路由規(guī)劃,或者說(shuō)控制器規(guī)劃是整個(gè)網(wǎng)站的骨架部分帐要,因?yàn)樗幱谡麄€(gè)架構(gòu)的樞紐位置把敞,相當(dāng)于各個(gè)接口之間的粘合劑,所以應(yīng)該優(yōu)先考慮榨惠。

根據(jù)構(gòu)思的設(shè)計(jì)圖先巴,我們作以下路由規(guī)劃:

/ :首頁(yè)
/login :用戶登錄
/reg :用戶注冊(cè)
/post :發(fā)表文章
/logout :登出

我們要求 /login 和 /reg 只能是未登錄的用戶訪問(wèn),而 /post 和 /logout 只能是已登錄的用戶訪問(wèn)冒冬。左側(cè)導(dǎo)航列表則針對(duì)已登錄和未登錄的用戶顯示不同的內(nèi)容伸蚯。

修改 index.js 如下:

// 路由控制器和實(shí)現(xiàn)路由功能的函數(shù),都在這個(gè)文件里

module.exports = function(app){
    // 主頁(yè)
    app.get('/', function(req, res) {
      res.render('index', { title: 'Express' });
    });
    
    // 注冊(cè),跳轉(zhuǎn)注冊(cè)頁(yè)
    app.get('/reg',function(req,res){
      res.render('reg',{title:'注冊(cè)'});   
    });
    // 注冊(cè)简烤,注冊(cè)操作
    app.post('/reg',function(req,res){

    });

    // 登錄,跳轉(zhuǎn)登錄頁(yè)
    app.get('/login',function(req,res){
      res.render('login',{title:'登錄'}); 
    });
    // 登錄剂邮,登錄操作
    app.post('/login',function(req,res){

    });

    // 發(fā)表,跳轉(zhuǎn)發(fā)表頁(yè)
    app.get('/post',function(req,res){
      res.render('post',{title:'發(fā)表'});
    });
    // 發(fā)表横侦,發(fā)表操作
    app.post('/post',function(req,res){

    });

    // 注銷
    app.get('/logout',function(req,res){
        
    });

};

使用數(shù)據(jù)庫(kù)


MongoDB簡(jiǎn)介

MongoDB 是一個(gè)基于分布式文件存儲(chǔ)的 NoSQL(非關(guān)系型數(shù)據(jù)庫(kù))的一種挥萌,由 C++ 語(yǔ)言編寫(xiě),旨在為 WEB 應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案枉侧。MongoDB 支持的數(shù)據(jù)結(jié)構(gòu)非常松散引瀑,是類似 json 的 bjson 格式,因此可以存儲(chǔ)比較復(fù)雜的數(shù)據(jù)類型榨馁。MongoDB 最大的特點(diǎn)是他支持的查詢語(yǔ)言非常強(qiáng)大憨栽,其語(yǔ)法有點(diǎn)類似于面向?qū)ο蟮牟樵冋Z(yǔ)言,幾乎可以實(shí)現(xiàn)類似關(guān)系數(shù)據(jù)庫(kù)單表查詢的絕大部分功能翼虫,而且還支持對(duì)數(shù)據(jù)建立索引屑柔。

MongoDB 沒(méi)有關(guān)系型數(shù)據(jù)庫(kù)中行和表的概念,不過(guò)有類似的文檔和集合的概念珍剑。文檔是 MongoDB 最基本的單位掸宛,每個(gè)文檔都會(huì)以唯一的 _id 標(biāo)識(shí),文檔的屬性為 key/value 的鍵值對(duì)形式招拙,文檔內(nèi)可以嵌套另一個(gè)文檔唧瘾,因此可以存儲(chǔ)比較復(fù)雜的數(shù)據(jù)類型措译。集合是許多文檔的總和,一個(gè)數(shù)據(jù)庫(kù)可以有多個(gè)集合饰序,一個(gè)集合可以有多個(gè)文檔领虹。

更多有關(guān) MongoDB 的知識(shí)請(qǐng)參閱 《mongodb權(quán)威指南》或查閱:http://www.mongodb.org/

安裝MongoDB

安裝 MongoDB 很簡(jiǎn)單,去官網(wǎng)下載對(duì)應(yīng)系統(tǒng)的 MongoDB 壓縮包即可。解壓后將文件夾重命名為 mongodb菌羽,并在 mongodb 文件夾里新建 blog 文件夾作為我們博客內(nèi)容的存儲(chǔ)目錄掠械。進(jìn)入到 bin 目錄下:運(yùn)行:

./mongod --dbpath ../blog/

以上命令的意思是:設(shè)置 blog 文件夾作為我們工程的存儲(chǔ)目錄并啟動(dòng)數(shù)據(jù)庫(kù)由缆。

連接MongoDB

數(shù)據(jù)庫(kù)雖然安裝并啟動(dòng)成功了注祖,但我們需要連接數(shù)據(jù)庫(kù)后才能使用數(shù)據(jù)庫(kù)。怎么才能在 Node.js 中使用 MongoDB 呢均唉?我們使用官方提供的 node-mongodb-native 驅(qū)動(dòng)模塊是晨,打開(kāi) package.json,在 dependencies 中添加一行:

"mongodb": "1.4.15"

然后運(yùn)行 npm install 更新依賴的模塊舔箭,稍等片刻后 mongodb 模塊就下載并安裝完成了罩缴。

創(chuàng)建setting.js文件

接下來(lái)在工程的根目錄中創(chuàng)建 settings.js 文件,用于保存該博客工程的配置信息层扶,比如數(shù)據(jù)庫(kù)的連接信息箫章。我們將數(shù)據(jù)庫(kù)命名為 blog,因?yàn)閿?shù)據(jù)庫(kù)服務(wù)器在本地镜会,所以 settings.js 文件的內(nèi)容如下:

module.exports = { 
  cookieSecret: 'myblog', 
  db: 'blog', 
  host: 'localhost',
  port: 27017
}; 

其中 db 是數(shù)據(jù)庫(kù)的名稱檬寂,host 是數(shù)據(jù)庫(kù)的地址,port是數(shù)據(jù)庫(kù)的端口號(hào)戳表,cookieSecret 用于 Cookie 加密與數(shù)據(jù)庫(kù)無(wú)關(guān)桶至,我們留作后用。

創(chuàng)建Models文件夾

接下來(lái)在根目錄下新建 models 文件夾匾旭,并在 models 文件夾下新建 db.js 镣屹,添加如下代碼:

var settings = require('../settings'),
    Db = require('mongodb').Db,
    Connection = require('mongodb').Connection,
    Server = require('mongodb').Server;
module.exports = new Db(settings.db, new Server(settings.host, settings.port),
{safe: true});

其中通過(guò) new Db(settings.db, new Server(settings.host, settings.port), {safe: true}); 設(shè)置數(shù)據(jù)庫(kù)名、數(shù)據(jù)庫(kù)地址和數(shù)據(jù)庫(kù)端口創(chuàng)建了一個(gè)數(shù)據(jù)庫(kù)連接實(shí)例价涝,并通過(guò) module.exports 導(dǎo)出該實(shí)例女蜈。這樣,我們就可以通過(guò) require 這個(gè)文件來(lái)對(duì)數(shù)據(jù)庫(kù)進(jìn)行讀寫(xiě)了色瘩。

打開(kāi) app.js鞭光,在 var routes = require('./routes/index'); 下添加:

var settings = require('./settings');

會(huì)話支持 session

express 也提供了會(huì)話中間件,默認(rèn)情況下是把用戶信息存儲(chǔ)在內(nèi)存中泞遗,但我們既然已經(jīng)有了 MongoDB惰许,不妨把會(huì)話信息存儲(chǔ)在數(shù)據(jù)庫(kù)中,便于持久維護(hù)史辙。為了使用這一功能汹买,我們需要借助 express-session 和 connect-mongo 這兩個(gè)第三方中間件佩伤,在 package.json 中添加:

"express-session": "1.9.1",
"connect-mongo": "0.4.1"    

注意: 如報(bào)"error setting ttl index on collection : sessions"錯(cuò)誤,把"mongodb"&"connect-mongo"版本號(hào)更到最新晦毙。

在package.json修改 "mongodb":“2.0.42”生巡, “connect-mongo”:“0.8.2” 運(yùn)行npm install安裝模塊,打開(kāi)app.js,添加以下代碼:

var session = require('express-session');
var MongoStore = require('connect-mongo')(session);

app.use(session({
  secret: settings.cookieSecret,
  key: settings.db,//cookie name
  cookie: {maxAge: 1000 * 60 * 60 * 24 * 30},//30 days
  store: new MongoStore({
    db: settings.db,
    host: settings.host,
    port: settings.port
  })
}));

注意: connect-mongo 最新版需要改成如:

store: new MongoStore({
  url: 'mongodb://localhost/blog'
})

使用 express-session 和 connect-mongo 模塊實(shí)現(xiàn)了將會(huì)化信息存儲(chǔ)到mongoldb中见妒。secret 用來(lái)防止篡改 cookie孤荣,key 的值為 cookie 的名字,通過(guò)設(shè)置 cookie 的 maxAge 值設(shè)定 cookie 的生存期须揣,這里我們?cè)O(shè)置 cookie 的生存期為 30 天盐股,設(shè)置它的 store 參數(shù)為 MongoStore 實(shí)例,把會(huì)話信息存儲(chǔ)到數(shù)據(jù)庫(kù)中耻卡,以避免丟失疯汁。在后面的小節(jié)中,我們可以通過(guò) req.session 獲取當(dāng)前用戶的會(huì)話對(duì)象卵酪,獲取用戶的相關(guān)信息幌蚊。

實(shí)現(xiàn)注冊(cè)和登陸


我們已經(jīng)準(zhǔn)備好了數(shù)據(jù)庫(kù)訪問(wèn)和會(huì)話的相關(guān)信息,接下來(lái)我們完成用戶注冊(cè)和登錄功能溃卡。

頁(yè)面設(shè)計(jì)

首先我們來(lái)完成主頁(yè)溢豆、登錄頁(yè)和注冊(cè)頁(yè)的頁(yè)面設(shè)計(jì)。

主頁(yè):index.ejs

<%- include header %>
這是主頁(yè)
<%- include footer %>

登錄頁(yè):login.ejs

<%- include header %>
    <form method="post">
      用戶名: <input type="text" name="name"/><br /><br />
      密   碼:  <input type="password" name="password"/><br /><br />
             <input type="submit" value="登錄"/>
             <input type="reset" value="重置"/>
    </form>
<%- include footer %>

注冊(cè)頁(yè): reg.ejs

<%- include header %>
    <form method="post">
      用戶名:    <input type="text" name="name"/><br /><br />
      密   碼:      <input type="password" name="password"/><br /><br />
      確認(rèn)密碼:<input type="password" name="password-repeat"/><br /><br />
      郵   箱:       <input type="email" name="email"/><br /><br />
               <input type="submit" value="注冊(cè)"/>
               <input type="reset" value="重置"/>
    </form>
<%- include footer %> 

到這里 啟動(dòng)我們的博客看看吧瘸羡!

實(shí)時(shí)更新組件

注意:每次我們更新代碼后漩仙,都需要手動(dòng)停止并重啟應(yīng)用,使用 supervisor 模塊可以解決這個(gè)問(wèn)題最铁,每當(dāng)我們保存修改的文件時(shí)讯赏,supervisor 都會(huì)自動(dòng)幫我們重啟應(yīng)用。通過(guò):

$ npm install -g supervisor

安裝 supervisor 冷尉。使用 supervisor 命令啟動(dòng) app.js:

$ supervisor app.js

頁(yè)面通知

接下來(lái)我們實(shí)現(xiàn)用戶的注冊(cè)和登陸漱挎,在這之前我們需要引入 flash 模塊來(lái)實(shí)現(xiàn)頁(yè)面通知(即成功與錯(cuò)誤信息的顯示)的功能。

什么事Flash雀哨?

我們所說(shuō)的 flash 即 connect-flash 模塊(https://github.com/jaredhanson/connect-flash)磕谅,flash 是一個(gè)在 session 中用于存儲(chǔ)信息的特定區(qū)域。信息寫(xiě)入 flash 雾棺,下一次顯示完畢后即被清除膊夹。典型的應(yīng)用是結(jié)合重定向的功能,確保信息是提供給下一個(gè)被渲染的頁(yè)面捌浩。

在 package.json 添加一行代碼:

"connect-flash": "0.1.1"   

然后 npm install 安裝 connect-flash 模塊放刨。修改 app.js ,在 var settings = require('./settings'); 后添加:

var flash = require('connect-flash');   

在 app.set('view engine', 'ejs'); 后添加:

app.use(flash());

現(xiàn)在我們就可以使用 flash 功能了尸饺。

注冊(cè)響應(yīng)

前面我們已經(jīng)完成了注冊(cè)頁(yè)进统,當(dāng)然現(xiàn)在點(diǎn)擊注冊(cè)是沒(méi)有效果的助币,因?yàn)槲覀冞€沒(méi)有實(shí)現(xiàn)處理 POST 請(qǐng)求的功能,下面就來(lái)實(shí)現(xiàn)它螟碎。

在 models 文件夾下新建 user.js眉菱,添加如下代碼:

// 處理 用戶注冊(cè) 和 登錄
// 引入 連接數(shù)據(jù)庫(kù)實(shí)例 外部文件
var mongodb = require('./db');

// 獲取用戶的信息
function User(user) {
    this.name = user.name;
    this.password = user.password;
    this.email = user.email;
}

// 導(dǎo)出,發(fā)布出去
module.exports = User;

// 存儲(chǔ)用戶信息 prototype 原型
User.prototype.save = function(callback) {
    // Scheme 要存入數(shù)據(jù)庫(kù)的用戶文檔
    var user = {
        name : this.name,
        password : this.password,
        email: this.email
    };
    // 打開(kāi)數(shù)據(jù)庫(kù)
    mongodb.open(function(err,db) {
        if(err) {
            return callback(err);//錯(cuò)誤掉分,返回err信息
        }
        // 讀取 users 集合
        db.collection('users',function (err,collection) {
            if(err){
                mongodb.close();
                return callback(err);
            }
                    // 將用戶數(shù)據(jù)插入 users 集合
            collection.insert(user,{
                safe : true
            } , function(err,user) {
                mongodb.close();
                if(err) {
                    return callback(err);//錯(cuò)誤俭缓,返回err信息
                }
                callback(null,user[0]);//成功!err為null酥郭,并返回存儲(chǔ)后的用戶文檔
            });
        });
    });
};

// 讀取用戶信息

User.get = function(name,callback) {
    // 打開(kāi)數(shù)據(jù)庫(kù)
    mongodb.open(function(err,db) {
        if(err){
            return callback(err);
        }
        // 讀取users 集合
        db.collection('users',function(err,collection)
        {
            if(err) {
                mongodb.close();
                return callback(err);
            }
            // 查找用戶名(name 鍵)值為 name 的一個(gè)文檔
            collection.findOne({name:name},function(err,user){
                if(err) {
                    return callback(err);//失敾埂!返回錯(cuò)誤信息
                }
                callback(null,user);//成功褥民!返回查詢的用戶信息
            });
        });
    });
};

我們通過(guò) User.prototype.save 實(shí)現(xiàn)了用戶信息的存儲(chǔ)季春,通過(guò) User.get 實(shí)現(xiàn)了用戶信息的讀取洗搂。

打開(kāi) index.js 消返,在最前面添加如下代碼:

var crypto = require('crypto'),
    User = require('../models/user.js');

通過(guò) require() 引入 crypto 模塊和 user.js 用戶模型文件,crypto 是 Node.js 的一個(gè)核心模塊耘拇,我們用它生成散列值來(lái)加密密碼撵颊。

修改 index.js 中 app.post('/reg') 如下:

注意:我們把用戶信息存儲(chǔ)在了 session 里,以后就可以通過(guò) req.session.user 讀取用戶信息惫叛。
  • req.body: 就是 POST 請(qǐng)求信息解析過(guò)后的對(duì)象倡勇,例如我們要訪問(wèn) POST 來(lái)的表單內(nèi)的 name="password" 域的值,只需訪問(wèn) req.body['password'] 或 req.body.password 即可嘉涌。
  • res.redirect: 重定向功能妻熊,實(shí)現(xiàn)了頁(yè)面的跳轉(zhuǎn),更多關(guān)于 res.redirect 的信息請(qǐng)查閱:http://expressjs.com/api.html#res.redirect 仑最。
  • User:在前面的代碼中扔役,我們直接使用了 User 對(duì)象。User 是一個(gè)描述數(shù)據(jù)的對(duì)象警医,即 MVC 架構(gòu)中的模型亿胸。前面我們使用了許多視圖和控制器,這是第一次接觸到模型预皇。與視圖和控制器不同侈玄,模型是真正與數(shù)據(jù)打交道的工具,沒(méi)有模型吟温,網(wǎng)站就只是一個(gè)外殼序仙,不能發(fā)揮真實(shí)的作用,因此它是框架中最根本的部分鲁豪。

接下來(lái)我們實(shí)現(xiàn)當(dāng)注冊(cè)成功返回主頁(yè)時(shí)潘悼,左側(cè)導(dǎo)航顯示 HOME 洋丐、POST 、LOGOUT 挥等,右側(cè)顯示 注冊(cè)成功友绝! 字樣,即添加 flash 的頁(yè)面通知功能肝劲。

修改 header.ejs迁客,將 <nav></nav> 修改如下:

<nav>
<span><a title="主頁(yè)" href="/">home</a></span>
<% if (user) { %>
  <span><a title="發(fā)表" href="/post">post</a></span>
  <span><a title="登出" href="/logout">logout</a></span>
<% } else { %>
  <span><a title="登錄" href="/login">login</a></span>
  <span><a title="注冊(cè)" href="/reg">register</a></span>
<% } %>
</nav>

在 <article> 后添加如下代碼:

<% if (success) { %>
  <div><%= success %></div>
<% } %>
<% if (error) { %>
  <div><%= error %> </div>
<% } %>

修改 index.js ,將 app.get('/') 修改如下:

app.get('/', function (req, res) {
res.render('index', {
title: '主頁(yè)',
user: req.session.user,
success: req.flash('success').toString(),
error: req.flash('error').toString()
});
});

將 app.get('reg') 修改如下:

app.get('/reg', function (req, res) {
  res.render('reg', {
    title: '注冊(cè)',
    user: req.session.user,
    success: req.flash('success').toString(),
    error: req.flash('error').toString()
  });
});

現(xiàn)在運(yùn)行我們的博客辞槐,注冊(cè)成功后顯示如下:

注冊(cè)成功
注冊(cè)成功

這個(gè)時(shí)候訪問(wèn)別的就會(huì) 出現(xiàn)一個(gè) user is undefined掷漱。因?yàn)槠渌穆酚蛇€沒(méi)傳遞一個(gè)user 過(guò)去。

我們通過(guò)對(duì) session 的使用實(shí)現(xiàn)了對(duì)用戶狀態(tài)的檢測(cè)榄檬,再根據(jù)不同的用戶狀態(tài)顯示不同的導(dǎo)航信息卜范。
簡(jiǎn)單解釋一下流程:用戶在注冊(cè)成功后,把用戶信息存入 session 鹿榜,頁(yè)面跳轉(zhuǎn)到主頁(yè)顯示 注冊(cè)成功海雪! 的字樣。同時(shí)把 session 中的用戶信息賦給變量 user 舱殿,在渲染 index.ejs 文件時(shí)通過(guò)檢測(cè) user 判斷用戶是否在線奥裸,根據(jù)用戶狀態(tài)的不同顯示不同的導(dǎo)航信息。

success: req.flash('success').toString() 的意思是將成功的信息賦值給變量 success沪袭, error: req.flash('error').toString() 的意思是將錯(cuò)誤的信息賦值給變量 error 湾宙,然后我們?cè)阡秩?ejs 模版文件時(shí)傳遞這兩個(gè)變量來(lái)進(jìn)行檢測(cè)并顯示通知。

登錄與登出響應(yīng)

現(xiàn)在我們來(lái)實(shí)現(xiàn)用戶登錄的功能冈绊。

打開(kāi) index.js 侠鳄,將 app.post('/login') 修改如下:

app.post('/login', function (req, res) {
  //生成密碼的 md5 值
  var md5 = crypto.createHash('md5'),
      password = md5.update(req.body.password).digest('hex');
  //檢查用戶是否存在
  User.get(req.body.name, function (err, user) {
    if (!user) {
      req.flash('error', '用戶不存在!'); 
      return res.redirect('/login');//用戶不存在則跳轉(zhuǎn)到登錄頁(yè)
    }
    //檢查密碼是否一致
    if (user.password != password) {
      req.flash('error', '密碼錯(cuò)誤!'); 
      return res.redirect('/login');//密碼錯(cuò)誤則跳轉(zhuǎn)到登錄頁(yè)
    }
    //用戶名密碼都匹配后,將用戶信息存入 session
    req.session.user = user;
    req.flash('success', '登陸成功!');
    res.redirect('/');//登陸成功后跳轉(zhuǎn)到主頁(yè)
  });
});

將 app.get('/login') 修改如下:

app.get('/login', function (req, res) {
    res.render('login', {
        title: '登錄',
        user: req.session.user,
        success: req.flash('success').toString(),
        error: req.flash('error').toString()});
});

(這樣就不會(huì)出現(xiàn) 'user is not defined' 的錯(cuò)誤了)

接下來(lái)我們實(shí)現(xiàn)登出響應(yīng)死宣。修改 app.get('/logout') 如下:

app.get('/logout', function (req, res) {
  req.session.user = null;
  req.flash('success', '登出成功!');
  res.redirect('/');//登出成功后跳轉(zhuǎn)到主頁(yè)
});

注意:通過(guò)把 req.session.user 賦值 null 丟掉 session 中用戶的信息伟恶,實(shí)現(xiàn)用戶的退出。

登錄后頁(yè)面顯示如下:

登錄成功
登錄成功
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末十电,一起剝皮案震驚了整個(gè)濱河市知押,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鹃骂,老刑警劉巖台盯,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異畏线,居然都是意外死亡静盅,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蒿叠,“玉大人明垢,你說(shuō)我怎么就攤上這事∈醒剩” “怎么了痊银?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)施绎。 經(jīng)常有香客問(wèn)我溯革,道長(zhǎng),這世上最難降的妖魔是什么谷醉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任致稀,我火速辦了婚禮,結(jié)果婚禮上俱尼,老公的妹妹穿的比我還像新娘抖单。我一直安慰自己,他們只是感情好遇八,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布矛绘。 她就那樣靜靜地躺著,像睡著了一般押蚤。 火紅的嫁衣襯著肌膚如雪蔑歌。 梳的紋絲不亂的頭發(fā)上羹应,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天揽碘,我揣著相機(jī)與錄音,去河邊找鬼园匹。 笑死雳刺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裸违。 我是一名探鬼主播掖桦,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼供汛!你這毒婦竟也來(lái)了枪汪?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤怔昨,失蹤者是張志新(化名)和其女友劉穎雀久,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體趁舀,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赖捌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矮烹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片越庇。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡罩锐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卤唉,到底是詐尸還是另有隱情涩惑,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布桑驱,位于F島的核電站境氢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏碰纬。R本人自食惡果不足惜萍聊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悦析。 院中可真熱鬧寿桨,春花似錦、人聲如沸强戴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)骑歹。三九已至预烙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間道媚,已是汗流浹背扁掸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留最域,地道東北人谴分。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像镀脂,于是被迫代替她去往敵國(guó)和親牺蹄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容