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

方向分页


GraphQLQueryPager支持双向分页,即正方向和反方向的分页。

正向分页

正向分页是最常见的分页形式。它用于获取列表中的下一n项。根据我们的需求有许多选择 —— 无论我们使用一个还是两个,我们是否想使用一个或者偏移,我们是否想转换结果,等等 - 我们将检查使用单个查询中的游标。

let initialQuery = MyQuery(first: 10, after: nil)
let pager = GraphQLQueryPager(
client: client,
initialQuery: initialQuery,
extractPageInfo: { data in
CursorBasedPagination.Forward(
hasNext: data.values.pageInfo.hasNextPage ?? false,
endCursor: data.values.pageInfo.endCursor
)
},
pageResolver: { page, paginationDirection in
// As we only want to support forward pagination, we can return `nil` for reverse pagination
switch paginationDirection {
case .next:
return MyQuery(first: 10, after: page.endCursor ?? .none)
case .previous:
return nil
}
}
)

反向分页

反向分页用于获取列表中的前 n 项。虽然根据需求我们有很多选择——是使用一个还是两个查询,是希望使用游标还是偏移量,是否想要转换结果等——但我们将探讨使用单个查询与游标结合的方法。

let initialQuery = MyQuery(first: 10, after: nil)
let pager = GraphQLQueryPager(
client: client,
initialQuery: initialQuery,
extractPageInfo: { data in
CursorBasedPagination.Reverse(
hasNext: data.values.pageInfo.hasPrevious ?? false,
endCursor: data.values.pageInfo.startCursor
)
},
pageResolver: { page, paginationDirection in
// As we only want to support reverse pagination, we can return `nil` for forward pagination
switch paginationDirection {
case .next:
return nil
case .previous:
return MyQuery(first: 10, before: page.startCursor ?? .none)
}
}
)

双向分页

双向分页用于获取列表中下一个 n 项以及前 n 项。考虑到我们可以双向获取,这意味着最初的查询结果既不在列表的头部也不在尾部。在这个例子中,我们将探讨使用单个查询与游标结合的方法。

let pager = GraphQLQueryPager(
client: client,
initialQuery: MyQuery(first: 10, after: nil),
extractPageInfo: { data in
CursorBasedPagination.Bidirectional(
hasNext: data.values.pageInfo.hasNextPage ?? false,
endCursor: data.values.pageInfo.endCursor,
hasPrevious: data.values.pageInfo.hasPreviousPage ?? false,
startCursor: data.values.pageInfo.startCursor
)
},
pageResolver: { page, direction in
switch direction {
case .next:
return MyQuery(first: 10, after: page?.endCursor ?? .none)
case .previous:
return MyQuery(first: 10, before: page?.startCursor ?? .none)
}
}
)

自定义配置

通常,建议使用便利初始化器来创建配置好的 GraphQLQueryPager。然而,如果您需要自定义配置,可以直接使用 init 方法。如果您的应用程序只使用特定类型的分页,您可以声明一个可通用于整个应用的自定义 GraphQLQueryPager 便利初始化器。这允许您轻松地实例化分页器,无需担心应用程序不支持的情况。如果您的分页方案只支持向前分页和偏移量,您可以声明一个只支持向前分页和偏移量的自定义 GraphQLQueryPager 便利初始化器。在这个例子中,我们声明了两个正向偏移量分页的初始化器——一个是带有 transform 的,另一个不带:

extension GraphQLQueryPager {
static func makeForwardOffsetQueryPager<InitialQuery: GraphQLQuery>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Forward?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Forward
) -> GraphQLQueryPager where Model == PaginationOutput<InitialQuery, InitialQuery> {
GraphQLQueryPager.init(
client: client,
initialQuery: queryProvider(nil),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
guard direction == .next else { return nil }
return queryProvider(page)
}
)
}
static func makeForwardOffsetQueryPager<InitialQuery: GraphQLQuery, T>(
client: ApolloClientProtocol,
watcherDispatchQueue: DispatchQueue = .main,
queryProvider: @escaping (OffsetPagination.Forward?) -> InitialQuery,
extractPageInfo: @escaping (InitialQuery.Data) -> OffsetPagination.Forward,
transform: @escaping (InitialQuery.Data) throws -> Model
) -> GraphQLQueryPager where Model: RangeReplaceableCollection, T == Model.Element {
GraphQLQueryPager.init(
client: client,
initialQuery: queryProvider(nil),
watcherDispatchQueue: watcherDispatchQueue,
extractPageInfo: pageExtraction(transform: extractPageInfo),
pageResolver: { page, direction in
guard direction == .next else { return nil }
return queryProvider(page)
},
initialTransform: transform,
pageTransform: transform
)
}
}
private func pageExtraction<InitialQuery: GraphQLQuery, P: PaginationInfo, T>(
transform: @escaping (InitialQuery.Data) -> P
) -> (PageExtractionData<InitialQuery, InitialQuery, T>) -> P {
{ extractionData in
switch extractionData {
case .initial(let value, _), .paginated(let value, _):
return transform(value)
}
}
}
private func pageExtraction<InitialQuery: GraphQLQuery, PaginatedQuery: GraphQLQuery, P: PaginationInfo, T>(
initialTransform: @escaping (InitialQuery.Data) -> P,
paginatedTransform: @escaping (PaginatedQuery.Data) -> P
) -> (PageExtractionData<InitialQuery, PaginatedQuery, T>) -> P {
{ extractionData in
switch extractionData {
case .initial(let value, _):
return initialTransfom(value)
case .paginated(let value, _):
return paginatedTransform(value)
}
}
}
上一个
使用自定义响应模型
下一个
多查询分页
评价文章评价在GitHub上编辑编辑论坛Discord

©2024Apollo Graph Inc.,商号Apollo GraphQL。

隐私政策

公司