graphql新手包

GraphQl

GraphQL是一个旨在简化前端和后端之间通信的规范。它主要由服务端的 schema 语言和客户端的查询语言组成。
【_查询语法和 schema 语法几乎是相等的_】。

gql的 api 需要完整描述期望返回的数据,相对于RestFul API减少了数据的冗余。修改一下官网的示例:

// 描述你的数据
// 定义了一个名为Project的对象类型,该类型上有三个字段,并且字段拥有不同的数据类型
type Project {
  name: String
  tagline: String
  contributors: [User]
}

// 请求你所要的数据
// 请求project中,name值为字符串‘GraphQl’的数据,并返回他的tagline字段
{
  project(name: "GraphQL") {
    tagline
  }
}

// 得到可预测的结果
{
  "project": {
    "tagline": "A query language for APIs"
  }
}
  • gql 实体资源不能通过 URL 识别

  • 与 gql 服务器的全部数据交互基于一个指定的URL

  • 标准的 gql GET 请求

    http://myapi/graphql?query={me{name}}
    
    {
      me{
        name
      }
    }
  • 标准的 gql POST 请求

    content-type:application/json
    
    {
      "query": 查询的对象及参数,
      "operationName": "...",
      "variables": 变量形式的参数传参
    }
    
    // 并且一般会发起两次请求,先发一次OPTION,

gql 文件

  • 比较方便的管理 gql 接口的方式就是预先编写.graphql文件,方便复用和拓展。
// 在一个gql文件内声明多个query,需要命名query,并支持es6结构引用。单个query请求文件则可不命名。

query queryxxx(
  $variable1: String
  $variable2: [String]
){
  myCoWorkers(
    name:$variable1
    gender:$variable2
  ){
    name
    age
    gender
    nation
  }
}
  • 也可以在请求时手动编写(需安装’graphql-tag’)
$apollo.query(
  query:gql`query tagList {
      tags {
        id,
        label
      }
    }`
)

ApolloClient

Apollo是实现 gql 标准的客户端,(可以理解成使用 gql 的axios)。各大框架和开发场景都有对应的整合库,如VueApollo

常用 api/选项

https://vue-apollo.netlify.app/zh-cn/api/smart-query.html#%E9%80%89%E9%A1%B9

  • query 查询表(可以是 query,mutation)

  • variables 变量

  • fetchPolicy 缓存选项

    # cache-first[default]
    
    Apollo Client 首先对缓存执行查询。如果缓存中存在所有请求的数据,则返回该数据。否则,Apollo Client 会针对您的 GraphQL 服务器执行查询,并在缓存数据后返回该数据。
    
    # cache-only
    
    Apollo Client 仅针对缓存执行查询。在这种情况下,它永远不会查询您的服务器。
    如果缓存不包含所有请求字段的数据,则会引发错误。
    
    # cache-and-network
    
    Apollo Client 对缓存和 GraphQL 服务器执行完整查询。如果服务器端查询的结果修改了缓存字段,则查询会自动更新。
    
    # network-only
    
    Apollo Client 会针对您的 GraphQL 服务器执行完整查询,而无需先检查缓存。查询的结果存储在缓存中。
    
    # no-cache
    
    与 network-only 类似, 但不缓存结果。
    
    # standby
    
    使用与 cache-first 相同的逻辑,除了当基础字段值更改时此查询不会自动更新。您仍然可以使用 refetch 和 updateQueries 手动更新此查询。
  • pollInterval 轮询(间隔 x 毫秒)

  • fetchMore 加载更多(可以改变个别或全部参数发送同一个请求,需手动处理请求结果)

使用 Apollo(vue v2)

  • 安装Apollo

    yarn add vue-apollo graphql apollo-boost
    
    #  apollo-boost 是创建apollo client的懒人包,包含常用的默认值,无需繁琐的手动配置
    
    or
    
    npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
  • 封装ApolloClient

    import ApolloClient from "apollo-boost";
    const $apollo = new ApolloClient({uri:'xxx'})
    
    // or
    
    // 封装举例
    // 超时
    import ApolloLinkTimeout from "apollo-link-timeout";
    const timeoutLink = new ApolloLinkTimeout(30000);
    
    // 缓存
    import { InMemoryCache } from 'apollo-cache-inmemory'
    const cache = new InMemoryCache()
    
    // link
    const httpLink = createHttpLink({ uri: 'xxx' });
    const timeoutHttpLink = timeoutLink.concat(httpLink);
    
    const apolloClient = new ApolloClient({
      version:'',
      name:'',
      link: timeoutHttpLink,//同时提供时优先级高于uri,提供更精细化的配置
    
      cache: // InMemoryCache ({......}) 缓存控制 www.apollographql.com/docs/react/caching/cache-configuration/`
    
      defaultOptions:{
          watchQuery: {
            fetchPolicy: 'cache-and-network',
            errorPolicy: 'ignore',
          },
          query: {
            fetchPolicy: 'network-only',
            errorPolicy: 'all',
          },
          mutate: {
            errorPolicy: 'all',
          }
        }//'各种查询的默认策略'
    
      });
  • 使用方法

    • apollo provider

      使用 apollo 组件,需先生成apollo provider,为 vue 实例提供 apollo 能力

      Vue.use(VueApollo);
      
      const apolloProvider = new VueApollo({
      	defaultClient: apolloClient,
      });
      new Vue({
      	el: "#app",
      	// 像 vue-router 或 vuex 一样注入 apolloProvider
      	apolloProvider,
      	render: (h) => h(App),
      });

      引入后之后,在你的每个 vue 组件实例上将多出$apollo 对象指向 apollo 客户端。

      this.$apollo ===>
      {query:[....],
      }

      并且与 data 选项平行的 apollo 选择中可以自定义各种 gql 查询,并且他们的结果将作为 vue 变量来使用

      data(){
        return {
          a:1
        }
      },
      apollo:{
        fetchB:{
          query:...,
          variables:...,
          fetchPolicy:...,
          ...各种apollo的api选项
        }
      }
    • apollo 组件

      在组件模版中编写 gql 查询,同时通过插槽slot分发请求结果,分别有ApolloQuery,ApolloMutation,ApolloSubscribeToMore

      <template>
        <!-- Apollo 查询 -->
        <ApolloQuery :query="/* 一些查询 */">
          <!-- 结果将自动更新 -->
          <template slot-scope="{ result: { data, loading } }">
            <!-- 一些内容 -->
            <div v-if="loading">Loading...</div>
            <ul v-else>
              <li v-for="user of data.users" class="user">
                {{ user.name }}
              </li>
            </ul>
          </template>
        </ApolloQuery>
      </template>
    • 纯 api 封装

      基本上没有侵入性的使用方法,封装成函数式的 api,不需要在实例中插入Apollo Providervue.use(vueApollo)

      // 伪代码
      import apolloclient
      import gql图表文件
      // apollo请求基于promise
      export const xxxapi = async (params) => {
        return await $apollo.query({
          query:,
          variables:{},
          fetchPolicy,
          ...
          ...各种参数
        })
      }

      然后在你的 js 代码中引入,熟悉的味道熟悉的配方

小结

相较于restful少了大量处理数据的步骤,接口天然更加安全(参数类型参数数量对不上都会请求失败),apollo 功能也是十分强大(轮询,分页,缓存),再回去用 restful 会有一种略难受的感觉。并且后端的同学也表示舒服。

之后打算在别的项目里陆续试一试智能查询和 apollo 组件,看看有没有耦合度低的接入方式或者复用的 apollo 组件。


graphql新手包
http://yoursite.com/2022/01/04/graphql新手包/
作者
tatekii
发布于
2022年1月4日
许可协议