在描述一个问题和问题之前,基于这个问题,我需要说,它首先是架构问题,我已经用不同的关键字搜索了很多次答案或类似的东西,但总是得到诸如“你的第一个带有 Vue 和 Typescript 的 GraphQL 应用程序”。似乎我有一个更复杂的问题,需要更复杂的方式来回答,而且我相信,通过在那里提问,我至少可以获得我需要的第一个最小答案线索。
另外,如果我重复或问了这个问题,我也很抱歉,之前已经回答过了。通过stackoverflow的基本搜索没有给我任何结果。
所以,假设我们有一个 GraphQL 模式,它包含以下类型
type Company {
id: ID!
name: String!
code: String
address: Address
}
type Address {
id: ID!
city: String!
# here might be many other fields, but provided ones are enough to ask
}
我们在模式中也有查询
type Query {
companies (input: FindCompaniesInput!): [Company!]!
}
及其前端包装器
query Company ($input: FindCompaniesInput!, $withAddress: Boolean, $withCode: Boolean) {
companies(input) {
...CompanyItem
code @include(if: $withCode)
address @include(if: $withAddress) {
id
city
}
}
}
查询输入类型如下所示
type FindCompaniesInput {
ids: [ID!]
take: Int
offset: Int
nameLike: String
cityLike: String
}
在 7 个不同的 Vue 组件中,我需要根据类型Company
使用 query加载 4 个片段之一companies
。例如,对于下拉输入组件,我需要这个
fragment CompanyItem on Company {
id
name
}
但对于公司卡组件我需要
fragment CompanyCard on Company {
id
name
address {
city
}
}
等等。
现在,关于 Vue 应用程序。我将 Vue 与 Typescript 以及相关包(例如vue-class-component
和vue-property-decorator
. 为了从模式生成类型,我使用apollo-graphql
. 我设计的应用程序没有在 Vuex 中存储 graphql 实体对象。为此,我使用 mixins。我了解,基于 mixins 使用模式是有风险的,但我使用以下方法将风险降至最低(或者我认为我这样做了)
我声明了 mixin 上下文
import { CompanyItem } from '@/api/graphql/generated/fragments'
type CompanyMixinContext = {
items: CompanyItem
isPageLoading: boolean
}
@Component
export class CompanyMixin extends Vue {
// I swap place of 'mixin' suffix in name, to easily access it in vue-dev-tools
// component properties are sorted, so all inherited mixins display grouped
protected mixinCompany: CompanyMixinContext = {
items: null
isPageLoading: false
}
protected async queryCompaniesPage(input: FindCompaniesInput) {
// ...here I query companies chunk and wrap it in try/catch/finally
}
}
然后,当它需要时,我使用 mixin 扩展我的组件。
<script lang="ts">
// omit imports...
@Component
export default MyComponent extends CompanyItemMixin {
// To use mixin context in template I declare a getter,
// omitting in its name a 'mixin' suffix
private get company () { return this.mixinCompany }
// The rest code of the component...
}
</script>
最后,当我展示了一个代码,它现在在我的应用程序中使用时,我现在可以提出一个问题。
有没有办法使用带有实体参数的单个查询,即使没有 mixins,但使用可重用的 vue+typescript 代码,能够根据变量返回正确的类型?
我不想编写 7 个函数,或者在我的情况下是 7 个 mixin,它们具有 99% 的相同代码并使用相同的 GQL 实体,但它们使用的类型仍然不同。
ps 使用 GraphQL 的主要特点是可以用不同的方式查询不同的实体结构,但是如何减少类似的代码来处理查询并使用一些通用的方法(vuex/mixins)来处理它对我来说仍然是一个谜。相信有很多高素质的前端工程师,能回答这个问题的,我就从这里开始寻找。
先感谢您。