iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
0
自我挑戰組

轉職道上的萌芽人生 − 自學程式開發ing系列 第 16

Day 16- 191002學習筆記 Express Route 設置

  • 分享至 

  • xImage
  •  

今天的任務是使用 Express Router middleware 來建立 Routes。
有了上一篇的經驗後,今天一樣直接先跳到後半段,先照著步驟建置好 Routes,再回頭來學習 Express Router middleware 的基本用法。


前言

request handling chain

  • 從前面的教學,已可以理解到 Database 的運作方式。我們藉由 Mongoose 建立了許多 Model ,裡面規範了資料的格式,以及建立一些方法來與 Database(MongoDb) 互動。
  • 接著再次從這張圖解來看:
    當收到 request 時,首先透過一套 Route 的規則,將不同的 request 指引到不同的 Controller 以進行不同的動作 -- 以藉由不同的 Model 來與 Database 進行互動、取得配對的 View -- 最後在 response 回去給客戶端呈現。

列出所需的 Routes

  • catalog/:首頁。
  • catalog/<objects>/: 每個 model 的目錄頁面
    (/catalog/books/:書本的目錄)。
  • catalog/<object>/<id>:每個 instance 的詳細資訊頁面
    (/catalog/book/584d37書本id = 584d37 的詳細資訊頁面)
  • catalog/<object>/create:對特定 model 建立新的 instance 的頁面
    (/catalog/book/create:新增新書頁面)
  • catalog/<object>/<id>/update:對特定 instance 進行更新的頁面
    (/catalog/book/584d37/update:更新 書本id = 584d37 的資料的頁面)
  • catalog/<object>/<id>/delete:刪除特定 instance 的頁面
    (/catalog/book/584d37/delete:刪除 書本id = 584d37 的頁面)
  • 可以使用id變數來編寫URL,因此每種特定動作只需使用一個 route 即可。
  • 編寫URL三原則:乾淨整潔、具邏輯性、具可讀性(參考W3C

建立 Controller 雛形

  • 將 Route 的 callback 分類寫進各個 Controller 中。
  • 接著先建立 Controller 的檔案雛形,以提供路徑給 Route 作設定。
  • 參考如下圖:
    https://ithelp.ithome.com.tw/upload/images/20191002/20120981B8rwsEJDFl.png
  • Controller 雛形大致如下:
// 先輸入models用以溝通database
const Book = require('../models/book')
// bookController多輸出一個index與首頁配對
exports.index = (req, res) => {res.send('Home Page')}
// 分別輸出一個callback以配對上述列出的URL
exports.book_list = (req, res) => {res.send('Book list')}
exports.book_detail = (req, res) => {res.send('Book detail: ' + req.params.id)}
exports.book_create_get = (req, res) => {res.send('Book create GET')}
exports.book_create_post = (req, res) => {res.send('Book create POST')}
exports.book_delete_get = (req, res) => {res.send('Book delete GET')}
exports.book_delete_post = (req, res) => {res.send('Book delete POST')}
exports.book_update_get = (req, res) => {res.send('Book update GET')}
exports.book_update_post = (req, res) => {res.send('Book update POST')}

建立 catalog route module

  • 首先在 routes 底下建立 catalog.js,以建立上述列舉 LocalLibrary 所需的 Routes。
  • 參考如下:
// 先輸入express,並定義 router 方法
const express = require('express')
const router = express.Router()
// 輸入 Controller,以建立每個 URL 與配對的 callback 連結
const bookController = require('../controllers/bookController')
// 建立routes----------------
// 首頁不會被變更,因此只需get
router.get('/', bookController.index)
// 注意此項必須在'/book/:id'前設置,否則會以為是要開啟id='create'。
router.get('/book/create', bookController.book_create_get)
router.post('/book/create', bookController.book_create_post)
// 可使用 :id 當變數,客製化不同 id 的 URL
router.get('/book/:id/delete', bookController.book_delete_get)
router.post('/book/:id/delete', bookController.book_delete_post)
router.get('/book/:id/update', bookController.book_update_get)
router.post('/book/:id/update', bookController.book_update_post)
router.get('/book/:id', bookController.book_detail)
router.get('/books', bookController.book_list)
// 輸出模組
module.exports = router

更新 index route module / app.js

  • 由於新的配置,首頁的 URL 已改為 'catalog/',因此需對 /routes/index.js 進行更新。
  • 使用 redirect() ,使其可自動跳轉到首頁正確的 URL。
router.get('/', (req, res) =>  {
  res.redirect('/catalog')
})
  • 由於我們新增了一個 route(catalog.js),因此需將其如同其他 route 一樣,新增至 app.js。
const catalogRouter = require('./routes/catalog')
// ...
app.use('/catalog', catalogRouter)

測試

  • 啟動網站後,輸入上述設定的各個 URL 測試其是否以設定成功。

Express Router 基本用法

  • 使用 Express Router 來建立 Routes 可以輕易將站點進行分類,並使用 route-prefix 即可進行連結。

  • Express Router 主要設定三個部分:HTTP verbs(甲)、Route paths(乙)、Route functions(丙)。(請求的類別、路徑、後續動作)
    語法:router.甲(乙, 丙)
    對 乙 路徑進行 甲 請求,以 丙 動作作為回應。

  • HTTP verbs: Router 提供的方法可以對應到所有的 HTTP verbs,如:get(), post(), put(), delete()等。
    例:router.get(乙, 丙)

  • Route paths

    • 使用 string 來表示URL路徑。
      例:router.get('/abc', 丙)
    • 也可以使用 string patterns 來表達:(可以多個URL指向同一個路徑)
      例:以 '/ab?cd' 書寫:網址輸入/acd 或 /abcd會指向該相同路徑。
      • ?:前面的字可出現0、1次。
        例:'/ab?cd':表示為 acd 或 abcd。
      • +:前面的字至少出現1次。
        例:'/ab+cd':表示為 abcd、abbcd、abbbbbbcd ...等。
      • *:前面的字可替換成任意字。
        例:'/ab*cd':表示為 abcd、abXcd、abOMyGodcd ...等。
      • ():將一串字組成一個群體,一起套用上述規則。
        例:'/ab(cd)?e':表示為 abe 或 abcde。
    • 也可以使用JS RegExp表達。
  • Route functions

    • 其中包含三個參數,也可只用兩個參數(req, res)。
    • 必須有做 res(回應動作) 或 next(跳下一個),才會結束請求。
      例:router.get('/abc', (req, res, next) => {res.send('Hi')})
    • respond 的方法
  • Route parameters:

    • 可捕獲在URL中的位置指定的ID,再以參數(變數)型式,書寫在URL中。(以冒號表示參數)
      例:以'/users/:userId/books/:bookId'書寫,當其取得指定ID時,:userId:bookId會帶入其捕獲的ID,以形成特定的URL。
    • URL 傳入後,會與第一個可以配對到的 Route 配對並使用使用該 Route。
      例:假設 Route: /book/:bookId 在 Route: /book/create 之前定義,則當 URL = '/book/create' 傳入後,會以為要開啟 id='create' 的 Route: /book/:bookId ,因此在定義 /book/:bookId 的 Route 前,須先定義 /book/create 的 Route。
  • 使用建立好的 Route 腳本:

// 輸入腳本
const name = require('腳本所在路徑')
// ...
// 收到指定的URL的 request 時,啟動該腳本
app.use('指定的URL', name)

上一篇
Day 15- 191001學習筆記 Mongoose
下一篇
Day 17- 191003學習筆記 async、Pug、moment
系列文
轉職道上的萌芽人生 − 自學程式開發ing30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言