Vapor 大型教程
全部分类页
本章实现网站上的「分类」相关页面:一个列出所有分类的列表页,以及点进去查看某分类下全部缩略语的详情页。
上下文与路由
在 WebsiteController.swift 中定义两个上下文:AllCategoriesContext 用于列表页;CategoryConext(源站原文如此命名)用于单个分类详情页,内部用一个 Future<[Acronym]> 承载该分类下的缩略语。
struct AllCategoriesContext: Encodable {
let title = "All Categories"
let categories: Future<[Category]>
}
struct CategoryConext: Encodable {
let title: String
let category: Category
let acronyms: Future<[Acronym]>
}
注册两条路由:/categories 显示全部分类,/category/:id 显示某个分类。
router.get("categories", use: allCategoriesHandler)
router.get("category", Category.parameter, use: categoryHandler)
列表页处理方法
allCategoriesHandler 用 Category.query(on: req).all() 取出所有分类,渲染 allCategories 模板。
func allCategoriesHandler(_ req: Request) throws -> Future<View> {
let categories = Category.query(on: req).all()
let context = AllCategoriesContext(categories: categories)
return try req.view().render("allCategories", context)
}
categoryHandler 先取出目标 Category,再通过 category.acronyms.query(on: req).all() 拿到它的关联缩略语,并渲染 category 模板。
func categoryHandler(_ req: Request) throws -> Future<View> {
return try req.parameters.next(Category.self)
.flatMap(to: View.self) { category in
let acronyms = try category.acronyms.query(on: req).all()
let context = CategoryConext(title: category.name, category: category, acronyms: acronyms)
return try req.view().render("category", context)
}
}
allCategories.leaf 模板
用表格展示分类名,每个名字链接到对应分类详情页;若还没有任何分类则显示提示文案。
#set("content"){
<h1>All Categories</h1>
#if(count(categories) > 0) {
<table class="table table-bordered table-hover">
<thead class="thead-light">
<tr>
<th>
Name
</th>
</tr>
<thead>
<tbody>
#for(category in categories) {
<tr>
<td>
<a href="/category/#(category.id)">
#(category.name)
</a>
</td>
</tr>
}
</tbody>
</table>
} else {
<h2>There aren't any categories yet!</h2>
}
}
#embed("base")
category.leaf 模板
展示分类名称,并用表格列出该分类下每个缩略语的简称与全称。
#set("content") {
<h1>#(category.name)</h1>
#if(count(acronyms) > 0) {
<table class="table table-bordered table-hover">
<thead class="thead-light">
<tr>
<th>
Short
</th>
<th>
Long
</th>
</tr>
</thead>
<tbody>
#for(acronym in acronyms) {
<tr>
<td>
<a href="/acronyms/#(acronym.id)">
#(acronym.short)
</a>
</td>
<td>
#(acronym.long)
</td>
</tr>
}
</tbody>
</table>
} else {
<h2>There aren't any acronyms yet!</h2>
}
}
#embed("base")
导航入口
在 base.leaf 加入「All Categories」导航项,访问本页时高亮。
<li class="nav-item #if(title=="All Categories"){active}">
<a href="/categories" class="nav-link">All Categories</a>
</li>