先決條件: | 閱讀 Express /節(jié)點(diǎn)簡(jiǎn)介。 完成上一篇教程主題(包括快速教程第3部分:使用數(shù)據(jù)庫(kù)(使用Mongoose))。 |
---|---|
目的: | 了解如何創(chuàng)建簡(jiǎn)單的路由。 設(shè)置所有的URL端點(diǎn)。 |
在上一篇教程文章中,我們定義了 Mongoose 模型以與數(shù)據(jù)庫(kù)進(jìn)行交互,并使用(獨(dú)立)腳本創(chuàng)建一些初始 圖書(shū)館記錄。 我們現(xiàn)在可以編寫(xiě)代碼以向用戶(hù)呈現(xiàn)該信息。 我們需要做的第一件事是確定我們希望在我們的頁(yè)面中顯示哪些信息,然后定義返回這些資源的適當(dāng)?shù)腢RL。 然后,我們需要?jiǎng)?chuàng)建路由(URL處理程序)和視圖(模板)來(lái)顯示這些頁(yè)面。
下面的圖提供了處理HTTP請(qǐng)求/響應(yīng)時(shí)需要實(shí)現(xiàn)的數(shù)據(jù)和事物的主要流程的提示。 除了視圖和路由之外,圖中還顯示了"controllers" - 分離出代碼以從實(shí)際處理請(qǐng)求的代碼中路由請(qǐng)求的函數(shù)。
由于我們已經(jīng)創(chuàng)建了模型,我們需要?jiǎng)?chuàng)建的主要內(nèi)容是:
最終,我們可能有頁(yè)面來(lái)顯示書(shū)籍,流派,作者和bookinstances的列表和詳細(xì)信息,以及創(chuàng)建,更新和刪除記錄的頁(yè)面。 這是一篇文章在一篇文章。 因此,本文大部分將集中在設(shè)置我們的路由和控制器返回"虛擬"內(nèi)容。 我們將在后續(xù)文章中擴(kuò)展控制器方法以使用模型數(shù)據(jù)。
下面的第一部分提供了有關(guān)如何使用Express"路由器"中間件的簡(jiǎn)要"初級(jí)"。 然后,當(dāng)我們?cè)O(shè)置LocalLibrary路由時(shí),我們將在以下部分使用該知識(shí)。
路由是Express代碼的一部分,其將HTTP動(dòng)詞( GET
, POST
, PUT
, DELETE
等等),URL路徑/模式,以及被調(diào)用以處理該模式的函數(shù)。
有幾種方法來(lái)創(chuàng)建路由。 在本教程中,我們將使用 express.Router
> 中間件,因?yàn)樗试S我們將網(wǎng)站特定部分的路由處理程序分組在一起,并使用公共路由前綴訪問(wèn)它們。 我們將所有的庫(kù)相關(guān)路由保存在一個(gè)"目錄"模塊中,如果我們添加了處理用戶(hù)帳戶(hù)或其他功能的路由,我們可以單獨(dú)分組。
注意:我們?cè)?a rel="external nofollow" target="_blank" > >快捷介紹> 創(chuàng)建路由處理程序。 除了為模塊化提供更好的支持(如下面第一小節(jié)所述),使用路由器與在 Express應(yīng)用程序?qū)ο?/em>上直接定義路由非常相似。
本節(jié)的其余部分提供了如何使用 Router
來(lái)定義路由的概述。
下面的代碼提供了一個(gè)具體的例子,說(shuō)明如何創(chuàng)建一個(gè)路由模塊,然后在一個(gè) Express 應(yīng)用程序中使用它。
首先,我們?cè)诿麨?strong> wiki.js 的模塊中創(chuàng)建wiki的路線。 代碼首先導(dǎo)入Express應(yīng)用程序?qū)ο螅褂盟鼇?lái)獲取一個(gè) Router
對(duì)象,然后使用 get()
方法添加一些路由到它。 最后模塊導(dǎo)出 Router
對(duì)象。
// wiki.js - Wiki route module
var express = require('express')
var router = express.Router()
// Home page route
router.get('/', function (req, res, next) {
res.send('Wiki home page')
})
// About page route
router.get('/about', function (req, res, next) {
res.send('About this wiki')
})
module.exports = router
注意:上面我們直接在路由器函數(shù)中定義我們的路由處理程序回調(diào)。 在LocalLibrary中,我們將在單獨(dú)的控制器模塊中定義這些回調(diào)。
要在我們的主要應(yīng)用程序文件中使用路由器模塊,我們首先使用 require()
路由模塊( wiki.js )。 然后,我們?cè)?em> Express 應(yīng)用程序上調(diào)用 use()
將路由器添加到中間件處理路徑,指定"wiki"的URL路徑。
var wiki = require('./wiki.js')
// ...
app.use('/wiki', wiki)
然后可以從 / wiki /
和 / wiki / about /
訪問(wèn)在wiki路由模塊中定義的兩個(gè)路由。
我們的模塊定義了幾個(gè)典型的路由功能。 使用 Router.get()
方法定義"約"路由(如下所述),該方法僅響應(yīng)HTTP GET請(qǐng)求。 此方法的第一個(gè)參數(shù)是URL路徑,而第二個(gè)是回調(diào)函數(shù),如果接收到具有路徑的HTTP GET請(qǐng)求,將調(diào)用該函數(shù)。
router.get('/about', function (req, res, next) {
res.send('About this wiki')
})
回調(diào)需要三個(gè)參數(shù)(通常如下所示: req
, res
, next
),它將包含HTTP請(qǐng)求對(duì)象,HTTP響應(yīng), 和中間件鏈中的下一個(gè)功能。
請(qǐng)注意:路由器功能 Express中間件 a>,這意味著它們必須完成(響應(yīng))請(qǐng)求或調(diào)用鏈中的下一個(gè)函數(shù)。 在上面的情況下,我們完成了請(qǐng)求,因此 next
參數(shù)沒(méi)有被實(shí)際使用。
此處的回調(diào)函數(shù)調(diào)用 send()
當(dāng)我們收到帶有路徑(\' / about\'
)的GET請(qǐng)求時(shí),返回字符串"About this wiki"的響應(yīng)。 有用于結(jié)束請(qǐng)求/響應(yīng)周期的其他響應(yīng)方法數(shù) 。 例如,您可以調(diào)用 res.json() / code>發(fā)送JSON響應(yīng)或
發(fā)送文件。 我們?cè)跇?gòu)建庫(kù)時(shí)最常使用的響應(yīng)方法是 render (),它使用模板和數(shù)據(jù)創(chuàng)建和返回HTML文件 - 我們將在后面的文章中進(jìn)一步討論這一點(diǎn)! res.sendFile()
a>
上面的示例路由使用 Router.get()
方法來(lái)響應(yīng)具有某個(gè)路徑的HTTP GET請(qǐng)求。
Router
還為所有其他HTTP動(dòng)詞提供路由方法,大多數(shù)使用方式完全相同: post()
, put
>, delete()
, options()
, trace()
(), mkcol()
, move()
, proppatch()
, unlock()
, checkout()
, merge()
, m-
/ code>, subscribe()
, unsubscribe()
code> connect()。
例如,下面的代碼與前面的 / about
路由一樣,但只響應(yīng)HTTP POST請(qǐng)求。
router.post('/about', function (req, res, next) {
res.send('About this wiki')
})
路由路徑定義可以進(jìn)行請(qǐng)求的端點(diǎn)。 到目前為止,我們看到的例子只是字符串,并且使用的是完全一樣的:\'/\',\'/ about\',\'/ book\',\'/any-random.path\'。
路由路徑也可以是字符串模式。 字符串模式使用正則表達(dá)式語(yǔ)法的子集來(lái)定義要匹配的端點(diǎn)的模式。 下面列出了子集(注意,連字符( -
)和點(diǎn)(。
)由字符串路徑解釋):
'/ab?cd'
will match endpoints acd
, abcd
, abbcd
etc.'/ab+cd'
will match endpoints abcd
, abbcd
, abbbcd
, and so on.'ab*cd'
will match endpoints abcd
, abXcd
, abSOMErandomTEXTcd
, and so on.'/ab(cd)?e'
will peform a ? match on (cd) —it will match abe
, abcde
, abcdcde
, and so on.路徑路徑也可以是JavaScript 正則表達(dá)式。 例如,下面的路由路徑將匹配 catfish
和 dogfish
匹配,但不匹配 catflap
, catfishhead
上。 請(qǐng)注意,正則表達(dá)式的路徑使用正則表達(dá)式語(yǔ)法(它不是以前情況下的帶引號(hào)的字符串)。
app.get(/.*fish$/, function (req, res) {
...
})
注意:LocalLibrary的大多數(shù)路由只使用字符串,而不是字符串模式和正則表達(dá)式。 我們還將使用下一節(jié)中討論的路由參數(shù)。
路線參數(shù)是用于捕獲在網(wǎng)址中在其位置處指定的值的命名的網(wǎng)址片段。 命名段的前綴為冒號(hào),然后是名稱(chēng)(例如 / : your_parameter_name /
。)捕獲的值存儲(chǔ)在 req.params
對(duì)象使用參數(shù)名作為鍵(例如 req.params.your_parameter_name
)。
例如,假設(shè)一個(gè)編碼為包含用戶(hù)和書(shū)籍信息的URL: http:// localhost:3000 / users / 34 / books / 8989
。 我們可以使用 userId
和 bookId
路徑參數(shù)來(lái)提取此信息:
app.get('/users/:userId/books/:bookId', function (req, res) {
// Access userId via: req.params.userId
// Access bookId via: req.params.bookId
res.send(req.params)
})
路由參數(shù)的名稱(chēng)必須由"字符"(A-Z,a-z,0-9和_)組成。
注意: / book / create 的網(wǎng)址將通過(guò) / book /:bookId
(將提取"bookId" of\' create
\')。 將使用與傳入U(xiǎn)RL匹配的第一個(gè)路由,因此如果您要分別處理 URL,則必須在您的
/ book /:bookId 代碼>路由。
這就是開(kāi)始使用路由所需要的 - 如果需要,您可以在Express文檔中找到更多信息: >基本路由和路由指南。 以下部分顯示了如何為L(zhǎng)ocalLibrary設(shè)置路由和控制器。
下面列出了我們最終需要用于我們網(wǎng)頁(yè)的網(wǎng)址,其中對(duì)象由每個(gè)模型的名稱(chēng)(book,bookinstance,genre,author), 是對(duì)象的復(fù)數(shù), 是默認(rèn)情況下給每個(gè)Mongoose模型實(shí)例賦予的唯一實(shí)例字段( _id
)。
catalog/
— The home/index page.catalog/<objects>/
— The list of all books, bookinstances, genres, or authors (e.g. /catalog/books/
, /catalog/genres/
, etc.)catalog/<object>/<id>
— The detail page for a specific book, bookinstance, genre, or author with the given _id
field value (e.g. /catalog/book/584493c1f4887f06c0e67d37)
.catalog/<object>/create
— The form to create a new book, bookinstance, genre, or author (e.g. /catalog/book/create)
.catalog/<object>/<id>/update
— The form to update a specific book, bookinstance, genre, or author with the given _id
field value (e.g. /catalog/book/584493c1f4887f06c0e67d37/update)
.catalog/<object>/<id>/delete
— The form to delete a specific book, bookinstance, genre, author with the given _id
field value (e.g. /catalog/book/584493c1f4887f06c0e67d37/delete)
.第一主頁(yè)和列表頁(yè)不編碼任何附加信息。 雖然返回的結(jié)果將取決于模型類(lèi)型和數(shù)據(jù)庫(kù)中的內(nèi)容,但運(yùn)行以獲取信息的查詢(xún)將始終相同(類(lèi)似地,用于對(duì)象創(chuàng)建的代碼運(yùn)行總是類(lèi)似的)。
相反,其他URL用于對(duì)特定文檔/模型實(shí)例進(jìn)行操作 - 這些URL對(duì)URL中的項(xiàng)目的標(biāo)識(shí)進(jìn)行編碼(如上所示的
。 我們將使用路徑參數(shù)提取編碼的信息,并將其傳遞給路由處理程序(在后面的文章中,我們將使用它來(lái)動(dòng)態(tài)確定從數(shù)據(jù)庫(kù)獲取什么信息)。 通過(guò)在我們的URL中編碼信息,我們只需要一個(gè)特定類(lèi)型的每個(gè)資源的一個(gè)路由(例如一個(gè)路由來(lái)處理每個(gè)單個(gè)書(shū)項(xiàng)目的顯示)。
注意:Express允許您以任何方式構(gòu)建網(wǎng)址 - 您可以按上面所示對(duì)網(wǎng)址正文中的信息進(jìn)行編碼,或使用URL GET
參數(shù)(例如 > / book /?id = 6
)。 無(wú)論您使用哪種方法,網(wǎng)址都應(yīng)保持干凈,邏輯和可讀(此處查看W3C建議 / a>)。
接下來(lái),我們?yōu)樗猩鲜鯱RL創(chuàng)建我們的路由處理程序回調(diào)函數(shù)和路由代碼。
在我們定義我們的路由之前,我們首先創(chuàng)建他們將調(diào)用的所有dummy / skeleton回調(diào)函數(shù)。 回調(diào)將存儲(chǔ)在Books,BookInstances,Genres和Authors的單獨(dú)的"控制器"模塊中(您可以使用任何文件/模塊結(jié)構(gòu),但這對(duì)于該項(xiàng)目似乎是一個(gè)適當(dāng)?shù)牧6?。
首先在項(xiàng)目根目錄( / controllers )中為控制器創(chuàng)建一個(gè)文件夾,然后創(chuàng)建用于處理每個(gè)模型的單獨(dú)的控制器文件/模塊:
/express-locallibrary-tutorial //the project root /controllers authorController.js bookController.js bookinstanceController.js genreController.js
打開(kāi) /controllers/authorController.js 文件,然后復(fù)制以下代碼:
var Author = require('../models/author'); // Display list of all Authors exports.author_list = function(req, res, next) { res.send('NOT IMPLEMENTED: Author list'); }; // Display detail page for a specific Author exports.author_detail = function(req, res, next) { res.send('NOT IMPLEMENTED: Author detail: ' + req.params.id); }; // Display Author create form on GET exports.author_create_get = function(req, res, next) { res.send('NOT IMPLEMENTED: Author create GET'); }; // Handle Author create on POST exports.author_create_post = function(req, res, next) { res.send('NOT IMPLEMENTED: Author create POST'); }; // Display Author delete form on GET exports.author_delete_get = function(req, res, next) { res.send('NOT IMPLEMENTED: Author delete GET'); }; // Handle Author delete on POST exports.author_delete_post = function(req, res, next) { res.send('NOT IMPLEMENTED: Author delete POST'); }; // Display Author update form on GET exports.author_update_get = function(req, res, next) { res.send('NOT IMPLEMENTED: Author update GET'); }; // Handle Author update on POST exports.author_update_post = function(req, res, next) { res.send('NOT IMPLEMENTED: Author update POST'); };
該模塊首先需要我們稍后將使用的模型來(lái)訪問(wèn)和更新我們的數(shù)據(jù)。 然后它導(dǎo)出我們希望處理的每個(gè)URL的函數(shù)(創(chuàng)建,更新和刪除操作使用表單,因此還有其他方法來(lái)處理表單發(fā)布請(qǐng)求 - 稍后我們將在"表單文章"中討論這些方法 )。
所有函數(shù)都具有 Express中間件函數(shù)的標(biāo)準(zhǔn)形式,如果方法未完成請(qǐng)求,則調(diào)用請(qǐng)求,響應(yīng)和 next
函數(shù)的參數(shù) 循環(huán)(在所有這些情況下,它!)。 這些方法只返回一個(gè)字符串,表示相關(guān)的頁(yè)面尚未創(chuàng)建。 如果控制器函數(shù)期望接收路徑參數(shù),則這些包括在消息字符串中。
打開(kāi) /controllers/bookinstanceController.js 文件,并在以下代碼中復(fù)制(與 Author
控制器模塊具有相同的模式):
var BookInstance = require('../models/bookinstance'); // Display list of all BookInstances exports.bookinstance_list = function(req, res, next) { res.send('NOT IMPLEMENTED: BookInstance list'); }; // Display detail page for a specific BookInstance exports.bookinstance_detail = function(req, res, next) { res.send('NOT IMPLEMENTED: BookInstance detail: ' + req.params.id); }; // Display BookInstance create form on GET exports.bookinstance_create_get = function(req, res, next) { res.send('NOT IMPLEMENTED: BookInstance create GET'); }; // Handle BookInstance create on POST exports.bookinstance_create_post = function(req, res, next) { res.send('NOT IMPLEMENTED: BookInstance create POST'); }; // Display BookInstance delete form on GET exports.bookinstance_delete_get = function(req, res, next) { res.send('NOT IMPLEMENTED: BookInstance delete GET'); }; // Handle BookInstance delete on POST exports.bookinstance_delete_post = function(req, res, next) { res.send('NOT IMPLEMENTED: BookInstance delete POST'); }; // Display BookInstance update form on GET exports.bookinstance_update_get = function(req, res, next) { res.send('NOT IMPLEMENTED: BookInstance update GET'); }; // Handle bookinstance update on POST exports.bookinstance_update_post = function(req, res, next) { res.send('NOT IMPLEMENTED: BookInstance update POST'); };
打開(kāi) /controllers/genreController.js 文件,并在以下文本中復(fù)制(與 Author
和 BookInstance
文件格式相同):
var Genre = require('../models/genre'); // Display list of all Genre exports.genre_list = function(req, res, next) { res.send('NOT IMPLEMENTED: Genre list'); }; // Display detail page for a specific Genre exports.genre_detail = function(req, res, next) { res.send('NOT IMPLEMENTED: Genre detail: ' + req.params.id); }; // Display Genre create form on GET exports.genre_create_get = function(req, res, next) { res.send('NOT IMPLEMENTED: Genre create GET'); }; // Handle Genre create on POST exports.genre_create_post = function(req, res, next) { res.send('NOT IMPLEMENTED: Genre create POST'); }; // Display Genre delete form on GET exports.genre_delete_get = function(req, res, next) { res.send('NOT IMPLEMENTED: Genre delete GET'); }; // Handle Genre delete on POST exports.genre_delete_post = function(req, res, next) { res.send('NOT IMPLEMENTED: Genre delete POST'); }; // Display Genre update form on GET exports.genre_update_get = function(req, res, next) { res.send('NOT IMPLEMENTED: Genre update GET'); }; // Handle Genre update on POST exports.genre_update_post = function(req, res, next) { res.send('NOT IMPLEMENTED: Genre update POST'); };
打開(kāi) /controllers/bookController.js 文件,并在以下代碼中復(fù)制。 它遵循與其他控制器模塊相同的模式,但另外還具有用于顯示站點(diǎn)歡迎頁(yè)面的 index()
函數(shù):
var Book = require('../models/book'); exports.index = function(req, res, next) { res.send('NOT IMPLEMENTED: Site Home Page'); }; // Display list of all books exports.book_list = function(req, res, next) { res.send('NOT IMPLEMENTED: Book list'); }; // Display detail page for a specific book exports.book_detail = function(req, res, next) { res.send('NOT IMPLEMENTED: Book detail: ' + req.params.id); }; // Display book create form on GET exports.book_create_get = function(req, res, next) { res.send('NOT IMPLEMENTED: Book create GET'); }; // Handle book create on POST exports.book_create_post = function(req, res, next) { res.send('NOT IMPLEMENTED: Book create POST'); }; // Display book delete form on GET exports.book_delete_get = function(req, res, next) { res.send('NOT IMPLEMENTED: Book delete GET'); }; // Handle book delete on POST exports.book_delete_post = function(req, res, next) { res.send('NOT IMPLEMENTED: Book delete POST'); }; // Display book update form on GET exports.book_update_get = function(req, res, next) { res.send('NOT IMPLEMENTED: Book update GET'); }; // Handle book update on POST exports.book_update_post = function(req, res, next) { res.send('NOT IMPLEMENTED: Book update POST'); };
接下來(lái),我們?yōu)長(zhǎng)ocalLibrary網(wǎng)站所需的所有網(wǎng)址創(chuàng)建路線,這將調(diào)用我們?cè)谏弦还?jié)中定義的控制器函數(shù)。
骨架已經(jīng)有 ./ routes 文件夾,其中包含 index 和用戶(hù)的路線。 在此文件夾中創(chuàng)建另一個(gè)路線文件 catalog.js ,如圖所示。
/express-locallibrary-tutorial //the project root /routes ? index.js ? users.js ? catalog.js
打開(kāi) /routes/catalog.js 并復(fù)制以下代碼:
var express = require('express'); var router = express.Router(); // Require controller modules var book_controller = require('../controllers/bookController'); var author_controller = require('../controllers/authorController'); var genre_controller = require('../controllers/genreController'); var book_instance_controller = require('../controllers/bookinstanceController'); /// BOOK ROUTES /// /* GET catalog home page. */ router.get('/', book_controller.index); /* GET request for creating a Book. NOTE This must come before routes that display Book (uses id) */ router.get('/book/create', book_controller.book_create_get); /* POST request for creating Book. */ router.post('/book/create', book_controller.book_create_post); /* GET request to delete Book. */ router.get('/book/:id/delete', book_controller.book_delete_get); // POST request to delete Book router.post('/book/:id/delete', book_controller.book_delete_post); /* GET request to update Book. */ router.get('/book/:id/update', book_controller.book_update_get); // POST request to update Book router.post('/book/:id/update', book_controller.book_update_post); /* GET request for one Book. */ router.get('/book/:id', book_controller.book_detail); /* GET request for list of all Book items. */ router.get('/books', book_controller.book_list); /// AUTHOR ROUTES /// /* GET request for creating Author. NOTE This must come before route for id (i.e. display author) */ router.get('/author/create', author_controller.author_create_get); /* POST request for creating Author. */ router.post('/author/create', author_controller.author_create_post); /* GET request to delete Author. */ router.get('/author/:id/delete', author_controller.author_delete_get); // POST request to delete Author router.post('/author/:id/delete', author_controller.author_delete_post); /* GET request to update Author. */ router.get('/author/:id/update', author_controller.author_update_get); // POST request to update Author router.post('/author/:id/update', author_controller.author_update_post); /* GET request for one Author. */ router.get('/author/:id', author_controller.author_detail); /* GET request for list of all Authors. */ router.get('/authors', author_controller.author_list); /// GENRE ROUTES /// /* GET request for creating a Genre. NOTE This must come before route that displays Genre (uses id) */ router.get('/genre/create', genre_controller.genre_create_get); /* POST request for creating Genre. */ router.post('/genre/create', genre_controller.genre_create_post); /* GET request to delete Genre. */ router.get('/genre/:id/delete', genre_controller.genre_delete_get); // POST request to delete Genre router.post('/genre/:id/delete', genre_controller.genre_delete_post); /* GET request to update Genre. */ router.get('/genre/:id/update', genre_controller.genre_update_get); // POST request to update Genre router.post('/genre/:id/update', genre_controller.genre_update_post); /* GET request for one Genre. */ router.get('/genre/:id', genre_controller.genre_detail); /* GET request for list of all Genre. */ router.get('/genres', genre_controller.genre_list); /// BOOKINSTANCE ROUTES /// /* GET request for creating a BookInstance. NOTE This must come before route that displays BookInstance (uses id) */ router.get('/bookinstance/create', book_instance_controller.bookinstance_create_get); /* POST request for creating BookInstance. */ router.post('/bookinstance/create', book_instance_controller.bookinstance_create_post); /* GET request to delete BookInstance. */ router.get('/bookinstance/:id/delete', book_instance_controller.bookinstance_delete_get); // POST request to delete BookInstance router.post('/bookinstance/:id/delete', book_instance_controller.bookinstance_delete_post); /* GET request to update BookInstance. */ router.get('/bookinstance/:id/update', book_instance_controller.bookinstance_update_get); // POST request to update BookInstance router.post('/bookinstance/:id/update', book_instance_controller.bookinstance_update_post); /* GET request for one BookInstance. */ router.get('/bookinstance/:id', book_instance_controller.bookinstance_detail); /* GET request for list of all BookInstance. */ router.get('/bookinstances', book_instance_controller.bookinstance_list); module.exports = router;
該模塊需要Express,然后使用它創(chuàng)建一個(gè) Router
對(duì)象。 所有路由都在路由器上設(shè)置,然后導(dǎo)出。
使用路由器對(duì)象上的 .get()
或 .post()
方法定義路由。 所有路徑都使用字符串(我們不使用字符串模式或正則表達(dá)式),使用某些特定資源(例如書(shū))的路由使用路徑參數(shù)從URL獲取對(duì)象ID。
處理程序函數(shù)都是從我們?cè)谏弦还?jié)中創(chuàng)建的控制器模塊導(dǎo)入的。
我們已經(jīng)設(shè)置了所有的新路線,但我們?nèi)匀挥幸粭l到原始頁(yè)面的路線。 讓我們將它重定向到我們?cè)诼窂絓'/ catalog\'創(chuàng)建的新索引頁(yè)面。
打開(kāi) /routes/index.js 并使用以下功能替換現(xiàn)有路線。
/* GET home page. */ router.get('/', function(req, res) { res.redirect('/catalog'); });
注意:這是我們首次使用 redirect() 響應(yīng)方法。 這將重定向到指定的頁(yè)面,默認(rèn)情況下發(fā)送HTTP狀態(tài)代碼"302 Found"。 如果需要,可以更改返回的狀態(tài)代碼,并提供絕對(duì)路徑或相對(duì)路徑。
最后一步是將路由添加到中間件鏈。 我們?cè)?code> app.js 中這樣做。
打開(kāi) app.js ,并要求目錄路徑在其他路線下方(以粗體顯示):
var index = require('./routes/index'); var users = require('./routes/users'); var catalog = require('./routes/catalog'); //Import routes for "catalog" area of site
接下來(lái),將目錄路由添加到中間件堆棧下面的其他路由,如下面粗體顯示:
app.use('/', index); app.use('/users', users); app.use('/catalog', catalog); // Add catalog routes to middleware chain.
注意:我們已將目錄模塊添加到路徑\'/ catalog\'
。 這是在目錄模塊中定義的所有路徑的前面。 因此,例如,要訪問(wèn)圖書(shū)列表,URL將是: / catalog / books /
。
而已。 我們現(xiàn)在應(yīng)該為我們最終將在LocalLibrary網(wǎng)站上支持的所有URL啟用路由和骨干功能。
要測(cè)試路線,首先使用您常用的方法啟動(dòng)網(wǎng)站
//Windows
SET DEBUG=express-locallibrary-tutorial:* & npm start
// Mac OS or Linux
DEBUG=express-locallibrary-tutorial:* npm start
//Windows
SET DEBUG=express-locallibrary-tutorial:* & npm run devstart
// Mac OS or Linux
DEBUG=express-locallibrary-tutorial:* npm run devstart
然后導(dǎo)航到多個(gè)LocalLibrary網(wǎng)址,并驗(yàn)證您沒(méi)有收到錯(cuò)誤頁(yè)面(HTTP 404)。 為方便起見(jiàn),下面列出了一小組網(wǎng)址:
我們現(xiàn)在創(chuàng)建了我們網(wǎng)站的所有路由,以及虛擬控制器函數(shù),我們可以在后面的文章中填充完整的實(shí)現(xiàn)。 一路上,我們學(xué)到了很多關(guān)于Express路由的基本信息,以及一些用于構(gòu)造我們的路由和控制器的方法。
在下一篇文章中,我們將使用視圖(模板)和存儲(chǔ)在模型中的信息為網(wǎng)站創(chuàng)建一個(gè)適當(dāng)?shù)臍g迎頁(yè)面。
更多建議: