圖書列表頁面
接下來,我們將實現我們的圖書列表頁面。此頁面需要顯示資料庫中所有圖書的列表,以及它們的作者,每個圖書標題都是指向其關聯的圖書詳情頁面的超連結。
控制器
圖書列表控制器函式需要獲取資料庫中所有Book物件列表,對其進行排序,然後將這些物件傳遞給模板進行渲染。
開啟/controllers/bookController.js。找到匯出的book_list()控制器方法,並將其替換為以下程式碼。
// 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()函式,選擇僅返回title和author,因為我們不需要其他欄位(它還會返回_id和虛擬欄位),並使用sort()方法按標題字母順序對結果進行排序。我們還在Book上呼叫populate(),指定author欄位——這將用完整的作者詳細資訊替換儲存的圖書作者 ID。然後,exec()在末尾連結,以執行查詢並返回一個 Promise。
路由處理程式使用await等待 Promise,暫停執行直到 Promise 完成。如果 Promise 已完成,則查詢結果將儲存到allBooks變數中,處理程式繼續執行。
路由處理程式的最後一部分呼叫render(),指定book_list(.pug)模板並將title和book_list的值傳遞到模板中。
檢視
建立/views/book_list.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/。然後選擇“所有圖書”連結。如果一切設定正確,您的網站應該如下面的螢幕截圖所示。
後續步驟
- 返回Express 教程第 5 部分:顯示庫資料。
- 繼續第 5 部分的下一個子文章:BookInstance 列表頁面。