GraphQL は、最近世界を席巻しました。 もともとはFacebookの特殊なユースケース向けに作成されましたが、開発シーン全体に広がり、現在では間違いなくクライアントサーバーデータ転送の最も好ましい方法になっています。 GraphQLイノベーションの最前線にあるのは、 Apollo です。これは、GraphQLクライアントとサーバーを作成するための独立したシステムグループです。 今日は、 vue-apollo を使用して、 apollo-client2をVue.jsと統合する方法を学習します。

インストール

残念ながら、 apollo-client には多くの依存関係があり、設定が面倒な場合があります。 順を追って説明します。

# Yarn
$ yarn vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-link-context apollo-cache-inmemory graphql-tag
# NPM
$ npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-link-context apollo-cache-inmemory graphql-tag

使用法

GraphQL / Apolloを追加する場合は、すでにVueでプロジェクトを設定している可能性がありますが、そうでない場合は、webpack-simpleに基づいて実行します。レンプレート。

次に、main.jsでApolloを設定する必要があります。 説明する価値のあるステップがいくつかあるので、それをチャンクに分割します。

main.js(インポート)
import Vue from 'vue';
import App from './App.vue';

// This is everything we need to work with Apollo 2.0.
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import VueApollo from 'vue-apollo';

// Register the VueApollo plugin with Vue.
Vue.use(VueApollo);

次に、ApolloのHTTPリンクを作成する必要があります。 Apollo 2.0は、プラグ可能なトランスポート/リンクシステムを持つように設計されているため、WebSocketまたは他のトランスポートモードからGraphQLAPIをロードできます。 何らかの理由で、これらのモードは「リンク」と呼ばれます。 用語で混乱させないでください。 🙂

main.js(Apollo Link)
// Create a new HttpLink to connect to your GraphQL API.
// According to the Apollo docs, this should be an absolute URI.
const httpLink = new HttpLink({
  uri: `https://somerandomgraphqlapi.com/api`
});

// I'm creating another variable here just because it makes it easier to add more links in the future.
const link = httpLink;

それが完了したら、Apolloクライアントをセットアップする必要があります。

main.js(Apolloクライアント)
// Create the apollo client
const apolloClient = new ApolloClient({
  // Tells Apollo to use the link chain with the http link we set up.
  link,
  // Handles caching of results and mutations.
  cache: new InMemoryCache(),
  // Useful if you have the Apollo DevTools installed in your browser.
  connectToDevTools: true,
});

了解しました。VueとVueApolloに次のことを伝える必要があります。 apolloClient

main.js(VueApolloセットアップ)
const apolloProvider = new VueApollo({
  // Apollo 2.0 allows multiple clients to be enabled at once.
  // Here we select the default (and only) client.
  defaultClient: apolloClient,
});

new Vue({
  // Inject apolloProvider for components to use.
  provide: apolloProvider.provide(),
  render: h => h(App),
}).$mount('#app');

VueアプリでApolloをセットアップするために必要なのはこれだけです。 完全なコードといくつかのヒントについては、以下を参照してください。 次のセクションでは、その使用方法を示します。

main.jsを完了します

import Vue from 'vue';
import App from './App.vue';
// This is everything we need to work with Apollo 2.0.
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import VueApollo from 'vue-apollo';

// Register the VueApollo plugin with Vue.
Vue.use(VueApollo);
// Create a new HttpLink to connect to your GraphQL API.
// According to the Apollo docs, this should be an absolute URI.
const httpLink = new HttpLink({
  uri: https://somerandomgraphqlapi.com/api
});
// I'm creating another variable here just because it
// makes it easier to add more links in the future.
const link = httpLink;
// Create the apollo client
const apolloClient = new ApolloClient({
  // Tells Apollo to use the link chain with the http link we set up.
  link,
  // Handles caching of results and mutations.
  cache: new InMemoryCache(),
  // Useful if you have the Apollo DevTools installed in your browser.
  connectToDevTools: true,
});
const apolloProvider = new VueApollo({
  // Apollo 2.0 allows multiple clients to be enabled at once.
  // Here we select the default (and only) client.
  defaultClient: apolloClient,
});

認証用のHTTPヘッダーの変更

多くの場合、送信される前にApolloによって作成されたHTTPリクエストにアクセスする必要があります。 たとえば、JWT認証ヘッダーを追加するため。 これは、setContextを使用してリンクを追加することで実行できます。 (これがapollo-link-contextへの依存関係です。 使用する必要がなかったことはありません。)

main.js
// Add this to your Apollo imports.
import { setContext } from 'apollo-link-context';

...

// Create a new Middleware Link using setContext
const middlewareLink = setContext(() => ({
  headers: {
    authorization: `Bearer ${HOWEVER_I_GET_MY_JWT}`
  }
}));

// Change your link assignment from
// const link = httpLink;
// to
const link = middlewareLink.concat(httpLink);

GraphQLクエリの作成

これで、コンポーネントでクエリを実行し、次のようにコンポーネントデータを自動入力することができます。

MyComponent.vue
<template>
  <p v-if="alligatorGraphQL">From GraphQL: {{alligatorGraphQL.name}}</p>
</template>

<script>
import gql from 'graphql-tag';

export default {
  data() {
    return {
      <span class="code-annotation">alligatorGraphQL: null</span>
    }
  },

  apollo: {
    // They key is the name of the data property
    // on the component that you intend to populate.
    alligatorGraphQL: {
      // Yes, this looks confusing.
      // It's just normal GraphQL.
      query: gql`
        query alligatorQuery($input: String!) {
          getAlligator(uuid: $input) {
            name
          }
        }
      `,

      variables: {
        // Some random UUID I generated.
        input: `03e082be-5e10-4351-a968-5f28d3e50565`
      },

      // Apollo maps results to the name of the query, for caching.
      // So to update the right property on the componet, you need to
      // select the property of the result with the name of the query.
      update: result => result.getAlligator,
    }
  }
}

(これは、サーバー側のスキーマがおおよそ次のとおりであることを前提としています:)

type Alligator {
  name: String
}

type Query {
  getAlligator(uuid: String!): Alligator
}

type Mutation {
  updateAlligatorName(name: String!): String
}

schema {
  query: Query
  mutation: Mutation
}

Protip:Vueコンポーネントのapollo {}のほとんどすべてのプロパティが反応する可能性があります。 したがって、リアクティブプロパティに基づいて変数またはクエリを変更する場合は、オブジェクトをコンポーネントデータに基づいてオブジェクトを返す関数に置き換えるだけです。

GraphQLミューテーションの作成

先に進んで上記のコンポーネントを変更し、ワニの名前を更新して読み取ることができるようにします。 このためには、GraphQLミューテーションが必要です。

MyComponent.vue
<template>
  <p>
    Alligator Name:
    <input type="text" v-if="alligatorGraphQL"
      :value="alligatorGraphQL.name" @input="temporaryName = $event.target.value"
    />
    <button @click="updateName">Update Name</button>
  </p>
</template>

<script>
import gql from 'graphql-tag';

export default {
  data() {
    return {
      temporaryName: '',
      alligatorGraphQL: null
    }
  },

  apollo: {
    alligatorGraphQL: {
      query: gql`
        query alligatorQuery($input: String!) {
          getAlligator(uuid: $input) {
            name
          }
        }
      `,

      variables: {
        input: `03e082be-5e10-4351-a968-5f28d3e50565`
      },

      update: result => result.getAlligator,
    }
  },

  methods: {
    updateName() {
      this.$apollo.mutate({
        mutation: gql`
          mutation ($name: String!) {
            updateAlligatorName(name: $name)
          }
        `,
        variables: { name: this.temporaryName }
      }).then(mutationResult => {
        // Do stuff with the result.
        console.log(`The Alligator's updated name is: ${mutationResult.data.updateAlligatorName}`)
      });

    }
  }
}
</script>

ここでは、v-modelまたは双方向バインディングの代わりに一時変数を使用していることに気付くでしょう。 これは、Apolloのデータ結果が読み取り専用で不変であるためです。 したがって、基本的に、GraphQLサーバーから取得するものはすべて、不変のリソースとして操作または処理する必要があります。

どうぞ! これで、ミューテーションが起動し、サーバーで必要な変更を加える必要があります。 (サーバーが正しく構成されている場合、つまり)

VueとApolloを使い始めるために必要なのはこれだけです。 詳細については、apollo-vueおよびApolloのドキュメントを参照してください。