Graphql前端状态管理

2018-12-21  本文已影响0人  anOnion

Graphql & Apollo

下图是2018年前端data layer工具的趋势图。我曾经在某一期博客提到过这张图,当时只注意了第二名的Graphql。后来发现排名第三的Apollo其实也是Graphql系列的工具,全名是apollo link state

Graphql & Apollo

Apollo也是使用Graphql语法管理数据,稍显不同的是它并不与后端通信,是纯粹的浏览器Local Data管理工具。Graphql在今年实现了前后端一统。

本期默认大家已经有了一定的vue和graphql背景知识,作为延伸学习,简单介绍一下Graphql在前端操作state management的一些方法。

vue-apollo

VUE主要通过vue-apollo集成Graphql Client框架。用法很简单,普通的插件集成。配一下默认的link和cache就可以连接后台graphql server了。(Apollo需要在link里加stateLink,后面再谈。)

vue-apollo-graphql
Vue.use(VueApollo);

const httpLink = new HttpLink( {uri: '/graphql'} );
const cache = new InMemoryCache();
// Create the apollo client
const apolloProvider = new VueApollo({
  defaultClient: new ApolloClient({link, cache})
});

new Vue({
  ...
  apolloProvider,
  ...
});

添加Apollo Provider后,我们不再需要通过mounted/created发起请求,一切数据处理委托给Graphql,通过apollo provider即可直接绑定客户端graphql cache的数据。从某种意义上来说,graphq cache可被视为一层data layer来管理SPA的全局state。因此Graphql推出不久,影响最大的不是后端的rest api,反倒是前端的Redux。

// in *.vue
<template>
    <div>Get Todos from server: {{ todos }}</div>
</template>

<script>
export default {
  apollo: {
    todos: gql`{
          todos: getTodos {
            id
            text
          }
        }
    `,
  },
   ...
}
<script>

Memory Cache

Memory Cache是Graphql存储数据的平台。如下所示,前端与后端交互后,Graphql客户端会在浏览器Cache里驻留response数据,然后通过这些全局缓存来管理状态。前端的graphql query默认的fetchPolicy是cache-first(顾名思义优先使用缓存,未命中则向后端请求数据,更新缓存后再渲染UI),除此之外还可以定制cache-and-networkcache-onlynetwork-only等策略。

Store data in Graphql cache

这里提一下,Memory Cache是通过key-value表单形式存储每一个对象。即便是数组内的对象也会被规格化存储。默认的primary key是id(或_id)和 __typename的组合键。当然也可以自定义主键

state update
如上图所示,点击UPDATE按钮后,触发的是某个对象的mutation操作,并未再次query State数组;但是mutation请求返回后更新了<id, __typename>主键对应的某块缓存,state数组也随之更新。
update () {
    this.$apollo.mutate({
        mutation: gql`mutation ($id: Int, $text: String!) {
            update(id: $id, text: $text) {
                id
                text
            }
            }`,
        variables: {
            id: 0,
            text: `Updated`,
        },
        });
    }

Apollo

今年下半年的时候Apollo大版本更新了graphql client,推出了apollo link state,我当时没及时更近后来还折腾了一番。

apollo client 2.0

Apollo Client开始支持Rest api和local state的数据管理。Apollo通过新的directive(@rest、@client)指向不同的数据。如下是一个拼接了Graphql、rest和local state的查询。

const getUser = gql`
  query getUser($id: String) {
    user(id: $id) {
      id
      name @rest(route: '/todos/name')
      cart @client
    }
  }
`;

Apollo遵循的还是Graphql的实现方式,只是把resolver放在了前端;通过直接读写cache里的数据更新state。这下就真没Redux什么事了。

const stateLink = withClientState({
  cache,
  resolvers: {
    Mutation: {
          addTodo: (_, { id, text }, { cache }) => {
        
          const newTodo = {id, text,  __typename: 'Todo'}
          const {todos} = cache.readQuery({ query });
          todos.push(newTodo)

          const data = { todos };
          cache.writeData({ data });
          return newTodo;
        },
  }
  }
});

const client = new ApolloClient({
  cache,
  link: ApolloLink.from([stateLink, new HttpLink()]),
});

小结

以上是这段时间我自己学习Apollo Graphql的一些总结。虽然接触不深,但还是可以感觉到Graphql带来的便捷。Apollo甚至给出了一套完整的前后端数据管理方案,初学者在前后端的学习成本变得更低了。相信2019年Graphql还会是前端开发的潮流,这种趋势已经不是rest、redux可阻挡的存在了。希望身边有更多小伙伴来和我一起学习,一起体验这种新的变化。

上一篇下一篇

猜你喜欢

热点阅读