加入我们,于10月8日至10日在纽约市,了解最新关于 GraphQL Federation 和 API 平台工程的技巧、趋势和新闻。加入我们参加 2024 年纽约市 GraphQL 大会
文档
免费开始

8. 分页结果


正如你可能已经注意到的,由LaunchListQuery 返回的对象是一个 LaunchConnection,该对象包含一个 列表、一个分页 ,以及一个布尔值来指示是否存在更多 launch。

当使用基于 cursor 的分页系统时,重要的是要记住,cursor 给你一个位置,无论在此期间是否添加了更多项目,你都可以在某个特定的位置之后获取所有结果。

在上一个部分中,你直接在 SMALL 尺寸 中硬编码了 ,但你也可以使用 程序化地定义参数。你将在这里使用它们来实现分页。

添加一个 cursor 变量

LaunchList.graphql 中添加一个 cursor 。在 GraphQL 中,变量的前缀是美元符号。

LaunchList.graphql
query LaunchList($cursor: String) {
launches(after: $cursor) {
hasMore
cursor
launches {
id
site
mission {
name
missionPatch(size: SMALL)
}
}
}
}

现在重新运行代码生成以更新 GraphQL 代码。

您可以在沙盒资源管理器中通过使用位于 下方的主体部分的窗格来">实验 GraphQL 变量。如果省略 $cursor 变量,服务器返回从开始的数据:

Explorer variables

LaunchListViewModel 更新为使用 cursor

首先,您需要保存最近收到的 LaunchConnection 对象。

LaunchListViewModel.swift 文件顶部添加一个变量来保存此对象,以及一个用于最近请求的变量,在您的 launches 变量附近:

LaunchListViewModel.swift
@Published var launches = [LaunchListQuery.Data.Launches.Launch]()
@Published var lastConnection: LaunchListQuery.Data.Launches?
@Published var activeRequest: Cancellable?
@Published var appAlert: AppAlert?
@Published var notificationMessage: String?

接下来,让我们更新我们的 loadMoreLaunches() 方法以使用 cursor 属性以及管理 lastConnectionactiveRequest 属性:

LaunchListViewModel.swift
private func loadMoreLaunches(from cursor: String?) {
self.activeRequest = Network.shared.apollo.fetch(query: LaunchListQuery(cursor: cursor ?? .null)) { [weak self] result in
guard let self = self else {
return
}
self.activeRequest = nil
switch result {
case .success(let graphQLResult):
if let launchConnection = graphQLResult.data?.launches {
self.lastConnection = launchConnection
self.launches.append(contentsOf: launchConnection.launches.compactMap({ $0 }))
}
if let errors = graphQLResult.errors {
self.appAlert = .errors(errors: errors)
}
case .failure(let error):
self.appAlert = .errors(errors: [error])
}
}
}

现在实现 loadMoreLaunchesIfTheyExist() 方法来检查是否有任何 launches 要加载,然后尝试加载它们。用以下代码替换 TODO

LaunchListViewModel.swift
func loadMoreLaunchesIfTheyExist() {
guard let connection = self.lastConnection else {
self.loadMoreLaunches(from: nil)
return
}
guard connection.hasMore else {
return
}
self.loadMoreLaunches(from: connection.cursor)
}

更新 UI 代码

接下来,转到 LaunchListView 并更新我们的任务以调用新实施的 loadMoreLaunchesIfTheyExist() 方法:

LaunchListView.swift
.task {
viewModel.loadMoreLaunchesIfTheyExist()
}

现在更新 List 添加一个按钮以在列表末尾加载更多 launches(可选):

LaunchListView.swift
List {
ForEach(0..<viewModel.launches.count, id: \.self) { index in
LaunchRow(launch: viewModel.launches[index])
}
if viewModel.lastConnection?.hasMore != false {
if viewModel.activeRequest == nil {
Button(action: viewModel.loadMoreLaunchesIfTheyExist) {
Text("Tap to load more")
}
} else {
Text("Loading...")
}
}
}

测试分页

构建并运行应用,当你滚动到列表底部时,你应该会看到一个显示 Tap to load more 的行:

Tap to load more

当你点击该行时,下批 launches 将被获取并加载到列表中。如果你继续此过程,最终 Tap to load more 按钮将不再显示,因为所有的 launches 都已经被加载。

Tap to load more

接下来,你将 完成详情视图 以允许你预订一次 的座位。

上一页
8. 给列表添加更多信息
下一页
10. 完成详情视图
评分文章评分在GitHub上编辑编辑论坛Discord

©2024Apollo Graph Inc.,即Apollo GraphQL。

隐私政策

公司