圖書列表頁面

接下來,我們將實現我們的圖書列表頁面。此頁面需要顯示資料庫中所有圖書的列表,以及它們的作者,每個圖書標題都是指向其關聯的圖書詳情頁面的超連結。

控制器

圖書列表控制器函式需要獲取資料庫中所有Book物件列表,對其進行排序,然後將這些物件傳遞給模板進行渲染。

開啟/controllers/bookController.js。找到匯出的book_list()控制器方法,並將其替換為以下程式碼。

js
// Display list of all books.
exports.book_list = asyncHandler(async (req, res, next) => {
  const allBooks = await Book.find({}, "title author")
    .sort({ title: 1 })
    .populate("author")
    .exec();

  res.render("book_list", { title: "Book List", book_list: allBooks });
});

路由處理程式在Book模型上呼叫find()函式,選擇僅返回titleauthor,因為我們不需要其他欄位(它還會返回_id和虛擬欄位),並使用sort()方法按標題字母順序對結果進行排序。我們還在Book上呼叫populate(),指定author欄位——這將用完整的作者詳細資訊替換儲存的圖書作者 ID。然後,exec()在末尾連結,以執行查詢並返回一個 Promise。

路由處理程式使用await等待 Promise,暫停執行直到 Promise 完成。如果 Promise 已完成,則查詢結果將儲存到allBooks變數中,處理程式繼續執行。

路由處理程式的最後一部分呼叫render(),指定book_list(.pug)模板並將titlebook_list的值傳遞到模板中。

檢視

建立/views/book_list.pug並將下面的文字複製到其中。

pug
extends layout

block content
  h1= title
  if book_list.length
    ul
      each book in book_list
        li
          a(href=book.url) #{book.title}
          |  (#{book.author.name})

  else
    p There are no books.

該檢視擴充套件了layout.pug基本模板並覆蓋了名為'content'的block。它顯示我們從控制器(透過render()方法)傳入的title,並使用each-in語法遍歷book_list變數。為每本書建立一個列表項,顯示圖書標題作為指向圖書詳情頁面的連結,後跟作者姓名。如果book_list中沒有圖書,則執行else子句,並顯示文字“沒有圖書”。

注意:我們使用book.url為每本書提供指向詳細資訊記錄的連結(我們已經實現了此路由,但尚未實現頁面)。這是Book模型的一個虛擬屬性,它使用模型例項的_id欄位生成唯一的 URL 路徑。

這裡值得注意的是,每本書被定義為兩行,使用管道符作為第二行。需要這種方法是因為如果作者姓名在上一行,那麼它將成為超連結的一部分。

它是什麼樣子的?

執行應用程式(有關相關命令,請參閱測試路由),並在瀏覽器中開啟https://:3000/。然後選擇“所有圖書”連結。如果一切設定正確,您的網站應該如下面的螢幕截圖所示。

Book List Page - Express Local Library site

後續步驟