该软件包目前提供对 Array
和 QueryBuilder
的偏移分页支持。
将 Paginator
添加到软件包依赖项 (在你的 Package.swift
文件中)
dependencies: [
...,
.package(url: "https://github.com/nodes-vapor/paginator.git", from: "4.0.0")
]
以及你的目标 (例如 "App")
targets: [
...
.target(
name: "App",
dependencies: [... "Paginator" ...]
),
...
]
接下来,将 Resources/Views/Paginator
文件夹复制/粘贴到你的项目中,以便能够使用提供的 Leaf 标签。 可以更改这些文件,如 Leaf 标签 部分中所述,但建议无论如何都将此文件夹复制到你的项目中。 这使你可以更轻松地跟踪更新,并且如果稍后你决定不使用自己的自定义 Leaf 文件,你的项目将可以正常工作。
首先,请确保已在所有需要的地方导入 Paginator
import Paginator
为了在 Leaf 中进行分页,请务必添加 Leaf 标签
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
services.register { _ -> LeafTagConfig in
var tags = LeafTagConfig.default()
tags.use([
"offsetPaginator": OffsetPaginatorTag(templatePath: "Paginator/offsetpaginator")
])
return tags
}
}
如果你想完全自定义分页控件的生成方式,可以自由覆盖模板路径。
要从 QueryBuilder
返回分页结果,可以执行以下操作
router.get("galaxies") { (req: Request) -> Future<OffsetPaginator<Galaxy>> in
return Galaxy.query(on: req).paginate(on: req)
}
为方便起见,Paginator 还支持对 Array
进行分页
router.get("galaxies") { (req: Request) -> Future<OffsetPaginator<Galaxy>> in
let galaxies = [Galaxy(), Galaxy(), Galaxy()]
return galaxies.paginate(on: req)
}
Paginator 还支持对原始 SQL 查询进行分页,用于与 Fluent 不兼容的复杂表达式。
使用 PostgreSQL 的简单示例
router.get("galaxies") { (req: Request) -> Future<OffsetPaginator<Galaxy>> in
return req.withPooledConnection(to: .psql) { conn -> Future<OffsetPaginator<Galaxy>> in
let rawBuilder = RawSQLBuilder<PostgreSQLDatabase, Galaxy>(
query: """
SELECT *
FROM public."Galaxy"
""", countQuery: """
SELECT COUNT(*) as "count"
FROM public."Galaxy"
""", connection: conn)
return try rawBuilder.paginate(on: req)
}
}
注意:计数查询应具有一个结果,该结果具有一个名为 count
的列,并且第一行包含总列数值
要将 Paginator 与 Leaf 一起使用,可以执行以下操作
struct GalaxyList: Codable {
let galaxies: [Galaxy]
}
router.get("galaxies") { (req: Request) -> Response in
let paginator: Future<OffsetPaginator<Galaxy>> = Galaxy.query(on: req).paginate(on: req)
return paginator.flatMap(to: Response.self) { paginator in
return try req.view().render(
"MyLeafFile",
GalaxyList(galaxies: paginator.data ?? []),
userInfo: try paginator.userInfo(),
on: req
)
.encode(for: req)
}
}
请注意如何使用
render
调用中的userInfo
传入 Paginator 数据。忘记传入此项将导致抛出错误。
然后在你的 MyLeafFile.leaf
中,你可以这样做
<ul>
#for(galaxy in galaxies) {
<li>#(galaxy.name)</li>
}
</ul>
#offsetPaginator()
调用 OffsetPaginator
的 Leaf 标签将自动生成 Bootstrap 4 HTML 以显示分页控件
<nav class="paginator">
<ul class="pagination justify-content-center table-responsive">
<li class="page-item">
<a href="/admin/users?page=16" class="page-link" rel="prev" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</a>
</li>
<li class="page-item "><a href="/admin/users?page=1" class="page-link">1</a></li>
<li class="disabled page-item"><a href="#" class="page-link">...</a></li>
<li class="page-item "><a href="" class="page-link">12</a></li>
<li class="page-item "><a href="" class="page-link">13</a></li>
<li class="page-item "><a href="" class="page-link">14</a></li>
<li class="page-item "><a href="" class="page-link">15</a></li>
<li class="page-item "><a href="" class="page-link">16</a></li>
<li class="page-item active "><a href="" class="page-link">17</a></li>
<li class="page-item "><a href="/admin/users?page=18" class="page-link">18</a></li>
<li class="page-item">
<a href="/admin/users?page=18" class="page-link" rel="next" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">Next</span>
</a>
</li>
</ul>
</nav>
可以通过映射分页器并一次转换每个元素来转换 OffsetPaginator 中的数据
Galaxy.query(on: req).paginate(on: req).map { paginator in
paginator.map { (galaxy: Galaxy) -> GalaxyViewModel in
GalaxyViewModel(galaxy: galaxy)
}
}
你也可以一次转换一整页结果
Galaxy.query(on: req).paginate(on: req).map { paginator in
paginator.map { (galaxies: [Galaxy]) -> [GalaxyViewModel] in
galaxies.map(GalaxyViewModel.init)
}
}
如果转换需要异步工作,你可以这样做
Galaxy.query(on: req).paginate(on: req).map { paginator in
paginator.flatMap { (galaxies: [Galaxy]) -> Future<[GalaxyViewModel]> in
galaxies.someAsyncMethod()
}
}
OffsetPaginator
有一个配置文件 (OffsetPaginatorConfig
),如果需要,可以覆盖它。 这可以在 configure.swift
中完成
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
// ..
services.register(OffsetPaginatorConfig(
perPage: 1,
defaultPage: 1
))
}
该软件包由 Nodes 的 Vapor 团队开发和维护。
该软件包是根据 MIT 许可证 获得许可的开源软件