1

在描述一个问题和问题之前,基于这个问题,我需要说,它首先是架构问题,我已经用不同的关键字搜索了很多次答案或类似的东西,但总是得到诸如“你的第一个带有 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-componentvue-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)来处理它对我来说仍然是一个谜。相信有很多高素质的前端工程师,能回答这个问题的,我就从这里开始寻找。

先感谢您。

4

0 回答 0