docs: Add Chinese Doc (#329)
* docs: structure of Chinese doc * docs: translate root page to Chinese * docs: translate pages in `/guide` and `/guid/apollo` to Chinese * docs: translate pages in `/api` and `/migration` to Chinese - fix some words in completed pages * docs: translate pages in `/guide/components` to Chinese * docs: fix some words * docs: keep Chinese version up to date * docs: Chinese version up to date * docs: fix some words * docs: fix some words
This commit is contained in:
+200
-89
@@ -1,104 +1,215 @@
|
||||
module.exports = {
|
||||
title: 'Vue Apollo',
|
||||
description: '🚀 Integrate GraphQL in your Vue.js apps!',
|
||||
base: '/vue-apollo/',
|
||||
serviceWorker: true,
|
||||
head: [
|
||||
['link', { rel: 'icon', href: '/favicon.png' }],
|
||||
],
|
||||
locales: {
|
||||
'/': {
|
||||
lang: 'en-US',
|
||||
title: 'Vue Apollo',
|
||||
description: '🚀 Integrate GraphQL in your Vue.js apps!',
|
||||
},
|
||||
'/zh-cn/': {
|
||||
lang: 'zh-CN',
|
||||
title: 'Vue Apollo',
|
||||
description: '🚀 在你的 Vue.js 应用中集成 GraphQL!',
|
||||
}
|
||||
},
|
||||
themeConfig: {
|
||||
repo: 'Akryum/vue-apollo',
|
||||
docsDir: 'docs',
|
||||
editLinks: true,
|
||||
lastUpdated: 'Last Updated',
|
||||
nav: [
|
||||
{
|
||||
text: 'Guide',
|
||||
link: '/guide/',
|
||||
locales: {
|
||||
'/': {
|
||||
selectText: 'Languages',
|
||||
label: 'English',
|
||||
lastUpdated: 'Last Updated',
|
||||
nav: [
|
||||
{
|
||||
text: 'Guide',
|
||||
link: '/guide/',
|
||||
},
|
||||
{
|
||||
text: 'API Reference',
|
||||
link: '/api/',
|
||||
},
|
||||
{
|
||||
text: 'Migration',
|
||||
link: '/migration/',
|
||||
},
|
||||
{
|
||||
text: 'CLI plugin',
|
||||
link: 'https://github.com/Akryum/vue-cli-plugin-apollo',
|
||||
},
|
||||
{
|
||||
text: 'Patreon',
|
||||
link: 'https://www.patreon.com/akryum',
|
||||
},
|
||||
],
|
||||
sidebarDepth: 3,
|
||||
sidebar: {
|
||||
'/guide/': [
|
||||
'',
|
||||
'installation',
|
||||
{
|
||||
title: 'Basic Usage',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'apollo/',
|
||||
'apollo/queries',
|
||||
'apollo/mutations',
|
||||
'apollo/subscriptions',
|
||||
'apollo/pagination',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Components',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'components/',
|
||||
'components/query',
|
||||
'components/mutation',
|
||||
'components/subscribe-to-more',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Advanced topics',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'multiple-clients',
|
||||
'ssr',
|
||||
'local-state',
|
||||
'testing',
|
||||
],
|
||||
},
|
||||
],
|
||||
'/api/': [
|
||||
{
|
||||
title: 'Vue Apollo',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'apollo-provider',
|
||||
'dollar-apollo',
|
||||
'ssr',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Smart Apollo',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'smart-query',
|
||||
'smart-subscription',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Apollo Components',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'apollo-query',
|
||||
'apollo-subscribe-to-more',
|
||||
'apollo-mutation',
|
||||
],
|
||||
},
|
||||
],
|
||||
'/migration/': [''],
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'API Reference',
|
||||
link: '/api/',
|
||||
'/zh-cn/': {
|
||||
selectText: '选择语言',
|
||||
label: '简体中文',
|
||||
editLinks: true,
|
||||
lastUpdated: '上次更新时间',
|
||||
nav: [
|
||||
{
|
||||
text: '指南',
|
||||
link: '/zh-cn/guide/',
|
||||
},
|
||||
{
|
||||
text: 'API 参考',
|
||||
link: '/zh-cn/api/',
|
||||
},
|
||||
{
|
||||
text: '迁移',
|
||||
link: '/zh-cn/migration/',
|
||||
},
|
||||
{
|
||||
text: 'CLI 插件',
|
||||
link: 'https://github.com/Akryum/vue-cli-plugin-apollo',
|
||||
},
|
||||
{
|
||||
text: '赞助作者',
|
||||
link: 'https://www.patreon.com/akryum',
|
||||
},
|
||||
],
|
||||
sidebarDepth: 3,
|
||||
sidebar: {
|
||||
'/zh-cn/guide/': [
|
||||
'',
|
||||
'installation',
|
||||
{
|
||||
title: '基本使用',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'apollo/',
|
||||
'apollo/queries',
|
||||
'apollo/mutations',
|
||||
'apollo/subscriptions',
|
||||
'apollo/pagination',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '组件',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'components/',
|
||||
'components/query',
|
||||
'components/mutation',
|
||||
'components/subscribe-to-more',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '进阶',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'multiple-clients',
|
||||
'ssr',
|
||||
'local-state',
|
||||
'testing',
|
||||
],
|
||||
},
|
||||
],
|
||||
'/zh-cn/api/': [
|
||||
{
|
||||
title: 'Vue Apollo',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'apollo-provider',
|
||||
'dollar-apollo',
|
||||
'ssr',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Smart Apollo',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'smart-query',
|
||||
'smart-subscription',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Apollo 组件',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'apollo-query',
|
||||
'apollo-subscribe-to-more',
|
||||
'apollo-mutation',
|
||||
],
|
||||
},
|
||||
],
|
||||
'/zh-cn/migration/': [''],
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Migration',
|
||||
link: '/migration/',
|
||||
},
|
||||
{
|
||||
text: 'CLI plugin',
|
||||
link: 'https://github.com/Akryum/vue-cli-plugin-apollo',
|
||||
},
|
||||
{
|
||||
text: 'Patreon',
|
||||
link: 'https://www.patreon.com/akryum',
|
||||
},
|
||||
],
|
||||
sidebarDepth: 3,
|
||||
sidebar: {
|
||||
'/guide/': [
|
||||
'',
|
||||
'installation',
|
||||
{
|
||||
title: 'Basic Usage',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'apollo/',
|
||||
'apollo/queries',
|
||||
'apollo/mutations',
|
||||
'apollo/subscriptions',
|
||||
'apollo/pagination',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Components',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'components/',
|
||||
'components/query',
|
||||
'components/mutation',
|
||||
'components/subscribe-to-more',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Advanced topics',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'multiple-clients',
|
||||
'ssr',
|
||||
'local-state',
|
||||
'testing',
|
||||
],
|
||||
},
|
||||
],
|
||||
'/api/': [
|
||||
{
|
||||
title: 'Vue Apollo',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'apollo-provider',
|
||||
'dollar-apollo',
|
||||
'ssr',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Smart Apollo',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'smart-query',
|
||||
'smart-subscription',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Apollo Components',
|
||||
collapsable: false,
|
||||
children: [
|
||||
'apollo-query',
|
||||
'apollo-subscribe-to-more',
|
||||
'apollo-mutation',
|
||||
],
|
||||
},
|
||||
],
|
||||
'/migration/': [''],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
home: true
|
||||
heroImage: /logo.png
|
||||
actionText: 由此起步 →
|
||||
actionLink: /zh-cn/guide/
|
||||
features:
|
||||
- title: 自动更新
|
||||
details: 无需考虑更新 UI 或重新获取查询的问题!
|
||||
- title: 模板内组件
|
||||
details: 通过 Apollo 组件声明式地使用 Apollo
|
||||
- title: 支持 SSR
|
||||
details: 在渲染 HTML 页面之前在服务端运行你的查询
|
||||
footer: LICENCE ISC - Created by Guillaume CHAU (@Akryum)
|
||||
---
|
||||
|
||||
<p style="text-align: center;">
|
||||
<a href="https://www.patreon.com/akryum" target="_blank">
|
||||
<img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Become a Patreon">
|
||||
</a>
|
||||
</p>
|
||||
@@ -0,0 +1,7 @@
|
||||
# API 参考
|
||||
|
||||
欢迎查看 API 参考!
|
||||
|
||||
::: warning Work-in-Progress
|
||||
如果你发现缺少了某些东西,请创建一个代码合并请求!
|
||||
:::
|
||||
@@ -0,0 +1,23 @@
|
||||
# ApolloMutation 组件
|
||||
|
||||
## Props
|
||||
|
||||
- `mutation`:GraphQL 查询(由 `graphql-tag` 转换)
|
||||
- `variables`:GraphQL 变量对象
|
||||
- `optimisticResponse`:详见 [乐观 UI](https://www.apollographql.com/docs/react/features/optimistic-ui.html)
|
||||
- `update`:详见 [变更后更新缓存](https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-mutation-options-update)
|
||||
- `refetchQueries`:详见 [变更后重新获取查询](https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-mutation-options-refetchQueries)
|
||||
- `clientId`:用于解析使用的 Apollo 客户端(在 ApolloProvider 中定义)
|
||||
- `tag`:字符串,HTML 标签名(默认值:`div`);如果是 `undefined`,该组件将成为无渲染组件(内容不会被包装在标签中)
|
||||
|
||||
## 作用域插槽 props
|
||||
|
||||
- `mutate(options = undefined)`:调用变更的函数。你可以重载变更的选项(例如:`mutate({ variables: { foo: 'bar } })`)
|
||||
- `loading`:布尔值,表明请求正在进行中
|
||||
- `error`:最后一次变更调用的最终错误
|
||||
- `gqlError`:第一个 GraphQL 错误(如果有)
|
||||
|
||||
## 事件
|
||||
|
||||
- `done(resultObject)`
|
||||
- `error(errorObject)`
|
||||
@@ -0,0 +1,47 @@
|
||||
# ApolloProvider
|
||||
|
||||
## 构造函数
|
||||
|
||||
```js
|
||||
const apolloProvider = new VueApollo({
|
||||
// 支持多客户端
|
||||
// 在查询中使用 'client' 选项
|
||||
// 或在 apollo 定义中使用 '$client'
|
||||
clients: {
|
||||
a: apolloClientA,
|
||||
b: apolloClientB,
|
||||
},
|
||||
// 默认客户端
|
||||
defaultClient: apolloClient,
|
||||
// 'apollo' 对象的默认定义
|
||||
defaultOptions: {
|
||||
// 详见 'apollo' 的定义
|
||||
// 例如:默认查询选项
|
||||
$query: {
|
||||
loadingKey: 'loading',
|
||||
fetchPolicy: 'cache-and-network',
|
||||
},
|
||||
},
|
||||
// 查看所有查询的加载状态
|
||||
// 详见 '智能查询 > 选项 > watchLoading'
|
||||
watchLoading (isLoading, countModifier) {
|
||||
loading += countModifier
|
||||
console.log('Global loading', loading, countModifier)
|
||||
},
|
||||
// 所有智能查询和订阅的全局错误处理函数
|
||||
errorHandler (error) {
|
||||
console.log('Global error handler')
|
||||
console.error(error)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
在你的 Vue 应用程序中使用 apollo provider:
|
||||
|
||||
```js
|
||||
new Vue({
|
||||
el: '#app',
|
||||
apolloProvider,
|
||||
render: h => h(App),
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# ApolloQuery 组件
|
||||
|
||||
## Props
|
||||
|
||||
- `query`:GraphQL 查询(由 `graphql-tag` 转换)
|
||||
- `variables`:GraphQL 变量对象
|
||||
- `fetchPolicy`:详见 [apollo fetchPolicy](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-fetchPolicy)
|
||||
- `pollInterval`:详见 [apollo pollInterval](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-pollInterval)
|
||||
- `notifyOnNetworkStatusChange`:详见 [apollo notifyOnNetworkStatusChange](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-notifyOnNetworkStatusChange)
|
||||
- `context`:详见 [apollo context](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-context)
|
||||
- `skip`:布尔值,禁用查询获取
|
||||
- `clientId`:用于解析使用的 Apollo 客户端(在 ApolloProvider 中定义)
|
||||
- `deep`:布尔值,使用深度 Vue 侦听器
|
||||
- `tag`:字符串,HTML 标签名(默认值:`div`);如果是 `undefined`,该组件将成为无渲染组件(内容不会被包装在标签中)
|
||||
- `debounce`:对重新获取查询结果的防抖毫秒数(例如当变量更改时)
|
||||
- `throttle`:对重新获取查询结果的节流毫秒数(例如当变量更改时)
|
||||
|
||||
## 作用域插槽
|
||||
|
||||
- `result`:Apollo 查询结果
|
||||
- `result.data`:查询返回的数据
|
||||
- `result.loading`:布尔值,表明请求正在进行中
|
||||
- `result.error`:当前结果的最终错误
|
||||
- `result.networkStatus`:详见 [apollo networkStatus](https://www.apollographql.com/docs/react/basics/queries.html#graphql-query-data-networkStatus)
|
||||
- `query`:与组件关联的智能查询
|
||||
- `isLoading`:智能查询加载状态
|
||||
- `gqlError`:第一个 GraphQL 错误(如果有)
|
||||
- `times`:结果被更新的次数
|
||||
|
||||
## 事件
|
||||
|
||||
- `result(resultObject)`
|
||||
- `error(errorObject)`
|
||||
@@ -0,0 +1,7 @@
|
||||
# ApolloSubscribeToMore 组件
|
||||
|
||||
## Props
|
||||
|
||||
- `document`:包含订阅的 GraphQL 文档。
|
||||
- `variables`:将自动更新订阅变量的对象。
|
||||
- `updateQuery`:可以根据需要更新查询结果的函数。
|
||||
@@ -0,0 +1,23 @@
|
||||
# Dollar Apollo
|
||||
|
||||
这是添加到任何使用 Apollo 的组件中的 Apollo 管理器。它可以在一个组件内通过 `this.$apollo` 访问到。
|
||||
|
||||
## 属性
|
||||
|
||||
- `vm`:关联的组件。
|
||||
- `queries`:组件的智能查询的数组。
|
||||
- `subscriptions`:组件的智能订阅的数组。
|
||||
- `client`:组件当前使用的 Apollo 客户端。
|
||||
- `provider`:注入的 [Apollo Provider](./apollo-provider.md)。
|
||||
- `loading`:是否至少有一个查询正在加载。
|
||||
- `skipAllQueries`:(setter) 布尔值,用于暂停或取消暂停所有智能查询。
|
||||
- `skipAllSubscriptions`:(setter) 布尔值,用于暂停或取消暂停所有智能订阅。
|
||||
- `skipAll`:(setter) 布尔值,用于暂停或取消暂停所有智能查询和智能订阅。
|
||||
|
||||
## 方法
|
||||
|
||||
- `query`:执行一个查询(详见 [查询](../guide/apollo/queries.md))。
|
||||
- `mutate`:执行一个变更(详见 [变更](../guide/apollo/mutations.md))。
|
||||
- `subscribe`:标准的 Apollo 订阅方法(详见 [订阅](../guide/apollo/subscriptions.md))。
|
||||
- `addSmartQuery`:手动添加一个智能查询(不推荐使用)。
|
||||
- `addSmartSubscription`:添加一个智能订阅(详见 [订阅](../guide/apollo/subscriptions.md))。
|
||||
@@ -0,0 +1,246 @@
|
||||
# 智能查询
|
||||
|
||||
在组件的 `apollo` 定义中声明的每个查询(不以 `$` 字符开头)都会创建一个智能查询对象。
|
||||
|
||||
## 选项
|
||||
|
||||
- `query`:GraphQL 文档(可以是一个文件或一个 `gql` 字符串)。
|
||||
- `variables`:对象或返回对象的响应式函数。每个键将用 `'$'` 映射到 GraphQL 文档中,例如 `foo` 将变为 `$foo`。
|
||||
- `throttle`:变量更新节流时间(毫秒)。
|
||||
- `debounce`:变量更新防抖时间(毫秒)。
|
||||
- `update(data) {return ...}` 用来自定义设置到 vue 属性中的值,例如当字段名称不匹配时。
|
||||
- `result(ApolloQueryResult)` 是收到结果时调用的钩子(更多参见 [ApolloQueryResult](https://github.com/apollographql/apollo-client/blob/master/packages/apollo-client/src/core/types.ts) 的文档)。
|
||||
- `error(error)` 是有错误时调用的钩子。`error` 是一个具有 `graphQLErrors` 属性或 `networkError` 属性的 Apollo 错误对象。
|
||||
- `loadingKey` 将更新你传递的值所对应的组件数据属性。你应该在组件的 `data()` 钩子中将此属性初始化为 `0` 。当查询正在加载时,此属性将增加 1;当不再加载时,它将减去 1。这样,该属性可以表示当前正在加载中的查询的计数器。
|
||||
- `watchLoading(isLoading, countModifier)` 是一个在查询的加载状态发生变化时调用的钩子。`countModifier` 参数当查询正在加载时等于 `1`,不再加载时为 `-1`。
|
||||
- `manual` 是一个禁用自动属性更新的布尔值。如果使用它,你需要指定一个 `result` 回调函数(参见下面的示例)。
|
||||
- `deep` 是一个在 Vue 侦听器上使用 `deep: true` 的布尔值。
|
||||
- `subscribeToMore`:一个或一组 [subscribeToMore 选项](../guide/apollo/subscriptions.md#subscribetomore) 对象。
|
||||
- `prefetch` 是一个布尔值或函数来确定是否应该预取查询。详见 [服务端渲染](../guide/ssr.md)。
|
||||
|
||||
示例:
|
||||
|
||||
```js
|
||||
// Apollo 具体选项
|
||||
apollo: {
|
||||
// 带参数的高级查询
|
||||
// vue 会侦听 'variables' 方法
|
||||
pingMessage: {
|
||||
query: gql`query PingMessage($message: String!) {
|
||||
ping(message: $message)
|
||||
}`,
|
||||
// 响应式参数
|
||||
variables() {
|
||||
// 在这里使用 vue 的响应式属性
|
||||
return {
|
||||
message: this.pingInput,
|
||||
}
|
||||
},
|
||||
// 变量:深度对象侦听
|
||||
deep: false,
|
||||
// 我们使用自定义更新回调,因为字段名称不匹配
|
||||
// 默认情况下,将使用 'data' 结果对象上的 'pingMessage' 属性
|
||||
// 考虑到 apollo 服务端的工作方式,我们知道结果是在 'ping' 属性中
|
||||
update(data) {
|
||||
console.log(data)
|
||||
// 返回的值将更新 vue 属性 'pingMessage'
|
||||
return data.ping
|
||||
},
|
||||
// 可选结果钩子
|
||||
result({ data, loading, networkStatus }) {
|
||||
console.log("We got some result!")
|
||||
},
|
||||
// 错误处理
|
||||
error(error) {
|
||||
console.error('We\'ve got an error!', error)
|
||||
},
|
||||
// 加载状态
|
||||
// loadingKey 是数据属性的名称
|
||||
// 在查询正在加载时将递增,不再加载时递减
|
||||
loadingKey: 'loadingQueriesCount',
|
||||
// 当加载状态发生变化时会调用 watchLoading
|
||||
watchLoading(isLoading, countModifier) {
|
||||
// isLoading 是一个布尔值
|
||||
// countModifier 为 1 或 -1
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
如果你使用 `ES2015`,`update` 也可以这样写:
|
||||
|
||||
```js
|
||||
update: data => data.ping
|
||||
```
|
||||
|
||||
手动模式示例:
|
||||
|
||||
```js
|
||||
{
|
||||
query: gql`...`,
|
||||
manual: true,
|
||||
result ({ data, loading }) {
|
||||
if (!loading) {
|
||||
this.items = data.items
|
||||
}
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 属性
|
||||
|
||||
### Skip
|
||||
|
||||
你可以使用 `skip` 来暂停或停止暂停:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.skip = true
|
||||
```
|
||||
|
||||
### loading
|
||||
|
||||
查询是否正在加载中:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.loading
|
||||
```
|
||||
|
||||
## 方法
|
||||
|
||||
### refresh
|
||||
|
||||
停止并重新启动查询:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.refresh()
|
||||
```
|
||||
|
||||
### start
|
||||
|
||||
开始查询:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.start()
|
||||
```
|
||||
|
||||
### stop
|
||||
|
||||
停止查询:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.stop()
|
||||
```
|
||||
|
||||
### fetchMore
|
||||
|
||||
为分页加载更多数据:
|
||||
|
||||
```js
|
||||
this.page++
|
||||
|
||||
this.$apollo.queries.tagsPage.fetchMore({
|
||||
// 新的变量
|
||||
variables: {
|
||||
page: this.page,
|
||||
pageSize,
|
||||
},
|
||||
// 用新数据转换之前的结果
|
||||
updateQuery: (previousResult, { fetchMoreResult }) => {
|
||||
const newTags = fetchMoreResult.tagsPage.tags
|
||||
const hasMore = fetchMoreResult.tagsPage.hasMore
|
||||
|
||||
this.showMoreEnabled = hasMore
|
||||
|
||||
return {
|
||||
tagsPage: {
|
||||
__typename: previousResult.tagsPage.__typename,
|
||||
// 合并标签列表
|
||||
tags: [...previousResult.tagsPage.tags, ...newTags],
|
||||
hasMore,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### subscribeToMore
|
||||
|
||||
使用 GraphQL 订阅来订阅更多数据:
|
||||
|
||||
```js
|
||||
// 我们需要在重新订阅之前取消订阅
|
||||
if (this.tagsSub) {
|
||||
this.tagsSub.unsubscribe()
|
||||
}
|
||||
// 在查询上订阅
|
||||
this.tagsSub = this.$apollo.queries.tags.subscribeToMore({
|
||||
document: TAG_ADDED,
|
||||
variables: {
|
||||
type,
|
||||
},
|
||||
// 变更之前的结果
|
||||
updateQuery: (previousResult, { subscriptionData }) => {
|
||||
// 如果我们在没有做操作的情况下已经添加了标签
|
||||
// 这可能是由 addTag 变更上的 `updateQuery` 导致
|
||||
if (previousResult.tags.find(tag => tag.id === subscriptionData.data.tagAdded.id)) {
|
||||
return previousResult
|
||||
}
|
||||
|
||||
return {
|
||||
tags: [
|
||||
...previousResult.tags,
|
||||
// 添加新的标签
|
||||
subscriptionData.data.tagAdded,
|
||||
],
|
||||
}
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### refetch
|
||||
|
||||
重新获取查询,可选择使用新变量:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.refetch()
|
||||
// 使用新变量
|
||||
this.$apollo.queries.users.refetch({
|
||||
friendsOf: 'id-user'
|
||||
})
|
||||
```
|
||||
|
||||
### setVariables
|
||||
|
||||
更新查询中的变量,如果发生了改变则重新获取查询。要强制重新获取,请使用 `refetch`。
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.setVariables({
|
||||
friendsOf: 'id-user'
|
||||
})
|
||||
```
|
||||
|
||||
### setOptions
|
||||
|
||||
更新 Apollo [watchQuery](https://www.apollographql.com/docs/react/api/apollo-client.html#ApolloClient.watchQuery) 选项并重新获取:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.setOptions({
|
||||
fetchPolicy: 'cache-and-network'
|
||||
})
|
||||
```
|
||||
|
||||
### startPolling
|
||||
|
||||
使用轮询启动自动更新(这意味着每隔 `x` ms 进行重新获取):
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.startPolling(2000) // ms
|
||||
```
|
||||
|
||||
### stopPolling
|
||||
|
||||
停止轮询:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.users.stopPolling()
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
# 智能订阅
|
||||
|
||||
每个在组件中的 `apollo.$subscribe` 选项中声明的订阅都会创建一个智能订阅对象。
|
||||
|
||||
## 选项
|
||||
|
||||
- `query`:GraphQL 文档(可以是一个文件或一个 `gql` 字符串)。
|
||||
- `variables`:对象或返回对象的响应式函数。每个键将用 `'$'` 映射到 GraphQL 文档中,例如 `foo` 将变为 `$foo`。
|
||||
- `throttle`:变量更新节流时间(毫秒)。
|
||||
- `debounce`:变量更新防抖时间(毫秒)。
|
||||
- `result(data)` 是收到结果时调用的钩子。
|
||||
|
||||
## 属性
|
||||
|
||||
### Skip
|
||||
|
||||
你可以使用 `skip` 来暂停或停止暂停:
|
||||
|
||||
```js
|
||||
this.$apollo.subscriptions.users.skip = true
|
||||
```
|
||||
|
||||
## 方法
|
||||
|
||||
### refresh
|
||||
|
||||
停止并重新启动查询:
|
||||
|
||||
```js
|
||||
this.$apollo.subscriptions.users.restart()
|
||||
```
|
||||
|
||||
### start
|
||||
|
||||
开始查询:
|
||||
|
||||
```js
|
||||
this.$apollo.subscriptions.users.start()
|
||||
```
|
||||
|
||||
### stop
|
||||
|
||||
停止查询:
|
||||
|
||||
```js
|
||||
this.$apollo.subscriptions.users.stop()
|
||||
```
|
||||
@@ -0,0 +1,55 @@
|
||||
# ApolloSSR
|
||||
|
||||
## 用法
|
||||
|
||||
详见 [SSR 指南](../guide/ssr.md).
|
||||
|
||||
## 方法
|
||||
|
||||
### prefetchAll
|
||||
|
||||
预取所有队列中的组件定义,并在所有对应的 apollo 数据准备就绪时返回已解决的(resolved) promise。
|
||||
|
||||
```js
|
||||
await ApolloSSR.prefetchAll (apolloProvider, componentDefs, context)
|
||||
```
|
||||
|
||||
`context` 作为参数传递给智能查询中的 `prefetch` 选项。它可能包含路由和 store。
|
||||
|
||||
### getStates
|
||||
|
||||
将 apollo store 状态作为 JavaScript 对象返回。
|
||||
|
||||
```js
|
||||
const states = ApolloSSR.getStates(apolloProvider, options)
|
||||
```
|
||||
|
||||
`options` 的默认值是:
|
||||
|
||||
```js
|
||||
{
|
||||
// 每个 apollo 客户端状态的 key 的前缀
|
||||
exportNamespace: '',
|
||||
}
|
||||
```
|
||||
|
||||
### exportStates
|
||||
|
||||
将 apollo store 状态作为字符串内的 JavaScript 代码返回。该代码可以直接注入到页面 HTML 的 `<script>` 标签中。
|
||||
|
||||
```js
|
||||
const js = ApolloSSR.exportStates(apolloProvider, options)
|
||||
```
|
||||
|
||||
`options` 的默认值是:
|
||||
|
||||
```js
|
||||
{
|
||||
// 全局变量名
|
||||
globalName: '__APOLLO_STATE__',
|
||||
// 变量设置到的全局对象
|
||||
attachTo: 'window',
|
||||
// 每个 apollo 客户端状态的 key 的前缀
|
||||
exportNamespace: '',
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
# 简介
|
||||
|
||||
::: danger
|
||||
本文档关联的版本仅支持 Apollo 2.x。查看支持 Apollo 1.x 的旧版本,请点击 [这里](https://github.com/Akryum/vue-apollo/tree/apollo-1).
|
||||
:::
|
||||
|
||||
这个库通过声明式查询将 [apollo](https://www.apollographql.com/) 集成到你的 [Vue](http://vuejs.org) 组件中。兼容 Vue 1.0+ 和 2.0+。[在线演示](https://jsfiddle.net/Akryum/oyejk2qL/)
|
||||
|
||||
## 赞助商
|
||||
|
||||
<p style="text-align: center; font-size: 24px; color: #9999A5;">
|
||||
<在这里加入你的 logo>
|
||||
</p>
|
||||
|
||||
## Become a sponsor
|
||||
|
||||
你的公司是否使用了 vue-apollo 或 vue-cli-plugin-apollo 来构建出色的应用程序?加入资助者并成为赞助商,在此文档中添加你的 logo!在 Patreon 上支持我,将节省我用于谋生的工作时间,从而能够在如 vue-apollo 一样的免费开源软件上工作更多!谢谢!
|
||||
|
||||
<p style="text-align: center;">
|
||||
<a href="https://www.patreon.com/akryum" target="_blank">
|
||||
<img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Become a Patreon">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 什么是 GraphQL?
|
||||
|
||||
[GraphQL](https://graphql.org/) 是一个旨在简化前端和后端之间通信的规范。它主要由服务端的 schema 语言和客户端的查询语言组成。
|
||||
|
||||
## 什么是 Apollo?
|
||||
|
||||
[Apollo](https://www.apollographql.com/) 是通过社区力量帮助你在应用中使用 GraphQL 的一套工具。它的 [客户端](https://www.apollographql.com/client) 和 [服务端](https://www.apollographql.com/server) 都非常有名。Apollo 由 [Meteor 开发团队](https://www.meteor.io/) 开发和支持。
|
||||
|
||||
## 链接
|
||||
|
||||
[<img src="https://assets-cdn.github.com/favicon.ico" alt="icon" width="16" height="16"/> Vue-cli 插件](https://github.com/Akryum/vue-cli-plugin-apollo)
|
||||
|
||||
[<img src="https://assets-cdn.github.com/favicon.ico" alt="icon" width="16" height="16"/> 更多 vue-apollo 示例](https://github.com/Akryum/vue-apollo-example)
|
||||
|
||||
[<img src="https://assets-cdn.github.com/favicon.ico" alt="icon" width="16" height="16"/> Apollo graphql server 示例](https://github.com/Akryum/apollo-server-example)
|
||||
|
||||
[<img src="http://graphql.cn/favicon.ico" alt="icon" width="16" height="16"/> GraphQL 中文文档](http://graphql.cn/)
|
||||
|
||||
[<img src="https://www.howtographql.com/static/howtographql.d1a2e5b4.svg" alt="icon" width="16" height="16"/> How to GraphQL](https://www.howtographql.com/vue-apollo/0-introduction/)
|
||||
|
||||
[<img src="https://conf.vuejs.org/img/logo-48.png" alt="icon" width="16" height="16"/> VueConf 2017 演示](https://github.com/Akryum/vueconf-2017-demo) & [讲义](http://slides.com/akryum/graphql#/)
|
||||
|
||||
[<img src="https://assets-cdn.github.com/favicon.ico" alt="icon" width="16" height="16"/> Devfest 峰会示例](https://github.com/Akryum/devfest-nantes-2017)(包括许多特性,如 SSR、OAuth、实时更新、Apollo Engine 等)
|
||||
@@ -0,0 +1,132 @@
|
||||
# 在 Vue 组件中使用 Apollo
|
||||
|
||||
要在你的 Vue 组件中声明 apollo 查询,只需添加一个 `apollo` 对象:
|
||||
|
||||
```js
|
||||
new Vue({
|
||||
apollo: {
|
||||
// Apollo 的具体选项
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
在你的每个 vue 组件中,你都可以通过 `this.$apollo.provider.defaultClient` 或 `this.$apollo.provider.clients.<key>`(用于 [多客户端](../multiple-clients.md))来访问 [apollo-client](https://www.apollographql.com/docs/react/) 实例。
|
||||
|
||||
## 查询(Queries)
|
||||
|
||||
为每个你需要通过 Apollo 的查询结果提供数据的 Vue 属性,在 `apollo` 对象中添加一个对应属性。
|
||||
|
||||
```js
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
apollo: {
|
||||
// 简单的查询,将更新 'hello' 这个 vue 属性
|
||||
hello: gql`query { hello }`,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
更多细节请查看 [查询](./queries.md) 一章。
|
||||
|
||||
## 变更(Mutations)
|
||||
|
||||
使用 `this.$apollo.mutate` 发送变更语句:
|
||||
|
||||
```js
|
||||
methods: {
|
||||
async addTag() {
|
||||
// 调用 graphql 变更
|
||||
const result = await this.$apollo.mutate({
|
||||
// 查询语句
|
||||
mutation: gql`mutation ($label: String!) {
|
||||
addTag(label: $label) {
|
||||
id
|
||||
label
|
||||
}
|
||||
}`,
|
||||
// 参数
|
||||
variables: {
|
||||
label: this.newTag,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
更多细节请查看 [变更](./mutations.md) 一章。
|
||||
|
||||
## 特殊选项
|
||||
|
||||
`apollo` 对象中的特殊选项以 `$` 开头表示。
|
||||
|
||||
- `$skip` 用于禁用所有查询和订阅(后文详述)
|
||||
- `$skipAllQueries` 用于禁用所有查询(后文详述)
|
||||
- `$skipAllSubscriptions` 用于禁用所有订阅(后文详述)
|
||||
- `$deep` 用于当为以上的属性提供函数时,通过 `deep: true` 进行监听
|
||||
- `$error` 用于捕获默认处理函数中的错误(详见智能查询的 `error` 高级选项)
|
||||
- `$query` 用于将默认选项应用于组件中的所有查询
|
||||
|
||||
示例:
|
||||
|
||||
```vue
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
loading: 0,
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
$query: {
|
||||
loadingKey: 'loading',
|
||||
},
|
||||
query1: { ... },
|
||||
query2: { ... },
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
你可以在 apollo provider 中为 `apollo` 定义一套默认选项。例如:
|
||||
|
||||
```js
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: apolloClient,
|
||||
defaultOptions: {
|
||||
// 将应用于组件中的所有查询的 apollo 选项
|
||||
$query: {
|
||||
loadingKey: 'loading',
|
||||
fetchPolicy: 'cache-and-network',
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## 全部跳过
|
||||
|
||||
你可以使用 `skipAllQueries` 禁用组件的所有查询,使用 `skipAllSubscriptions` 禁用所有订阅,或是使用 `skipAll` 将两者全部禁用:
|
||||
|
||||
```js
|
||||
this.$apollo.skipAllQueries = true
|
||||
this.$apollo.skipAllSubscriptions = true
|
||||
this.$apollo.skipAll = true
|
||||
```
|
||||
|
||||
你也可以在组件的 `apollo` 选项中声明这些属性。它们可以是布尔值:
|
||||
|
||||
```js
|
||||
apollo: {
|
||||
$skipAll: true
|
||||
}
|
||||
```
|
||||
|
||||
或是响应式函数:
|
||||
|
||||
```js
|
||||
apollo: {
|
||||
$skipAll () {
|
||||
return this.foo === 42
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,121 @@
|
||||
# 变更
|
||||
|
||||
变更是在你的 apollo 服务端更改你的数据状态的查询。
|
||||
|
||||
使用 `this.$apollo.mutate()` 来发送一个 GraphQL 变更。
|
||||
|
||||
想要了解更多信息,请访问 [apollo 文档](https://www.apollographql.com/docs/react/api/apollo-client.html#ApolloClient.mutate)。有一个以变更为重点的 [示例应用](https://github.com/Akryum/vue-apollo-todos),你可以看看。
|
||||
|
||||
::: warning
|
||||
你不应当在 variables 中发送 `__typename` 字段,因此不建议直接发送 Apollo 结果对象。
|
||||
:::
|
||||
|
||||
```js
|
||||
methods: {
|
||||
addTag() {
|
||||
// 保存用户输入以防止错误
|
||||
const newTag = this.newTag
|
||||
// 将其清除以尽早更新用户页面
|
||||
this.newTag = ''
|
||||
// 调用 graphql 变更
|
||||
this.$apollo.mutate({
|
||||
// 查询语句
|
||||
mutation: gql`mutation ($label: String!) {
|
||||
addTag(label: $label) {
|
||||
id
|
||||
label
|
||||
}
|
||||
}`,
|
||||
// 参数
|
||||
variables: {
|
||||
label: newTag,
|
||||
},
|
||||
// 用结果更新缓存
|
||||
// 查询将先通过乐观响应、然后再通过真正的变更结果更新
|
||||
update: (store, { data: { newTag } }) => {
|
||||
// 从缓存中读取这个查询的数据
|
||||
const data = store.readQuery({ query: TAGS_QUERY })
|
||||
// 将变更中的标签添加到最后
|
||||
data.tags.push(newTag)
|
||||
// 将数据写回缓存
|
||||
store.writeQuery({ query: TAGS_QUERY, data })
|
||||
},
|
||||
// 乐观 UI
|
||||
// 将在请求产生时作为“假”结果,使用户界面能够快速更新
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
addTag: {
|
||||
__typename: 'Tag',
|
||||
id: -1,
|
||||
label: newTag,
|
||||
},
|
||||
},
|
||||
}).then((data) => {
|
||||
// 结果
|
||||
console.log(data)
|
||||
}).catch((error) => {
|
||||
// 错误
|
||||
console.error(error)
|
||||
// 恢复初始用户输入
|
||||
this.newTag = newTag
|
||||
})
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
## 服务端示例
|
||||
|
||||
```js
|
||||
export const schema = `
|
||||
type Tag {
|
||||
id: Int
|
||||
label: String
|
||||
}
|
||||
|
||||
type Query {
|
||||
tags: [Tag]
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
addTag(label: String!): Tag
|
||||
}
|
||||
|
||||
schema {
|
||||
query: Query
|
||||
mutation: Mutation
|
||||
}
|
||||
`
|
||||
|
||||
// 假数据生成器
|
||||
import faker from 'faker'
|
||||
|
||||
// 生成一些标签
|
||||
var id = 0
|
||||
var tags = []
|
||||
for (let i = 0; i < 42; i++) {
|
||||
addTag(faker.random.word())
|
||||
}
|
||||
|
||||
function addTag(label) {
|
||||
let t = {
|
||||
id: id++,
|
||||
label,
|
||||
}
|
||||
tags.push(t)
|
||||
return t
|
||||
}
|
||||
|
||||
export const resolvers = {
|
||||
Query: {
|
||||
tags(root, args, context) {
|
||||
return tags
|
||||
},
|
||||
},
|
||||
Mutation: {
|
||||
addTag(root, { label }, context) {
|
||||
console.log(`adding tag '${label}'`)
|
||||
return addTag(label)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,95 @@
|
||||
# 使用 `fetchMore` 实现分页
|
||||
|
||||
*[这里](https://github.com/Akryum/apollo-server-example/blob/master/schema.js#L21) 是服务端的一个简单示例。*
|
||||
|
||||
有时候你的数据集非常大,你想分块加载它。
|
||||
|
||||
使用智能查询上的 `fetchMore()` 方法来加载更多数据。
|
||||
|
||||
::: warning
|
||||
不要忘记将 `__typename` 包含到新结果中。
|
||||
|
||||
使用 `variables()` 时不要更改返回的初始变量,否则列表数据将丢失。
|
||||
:::
|
||||
|
||||
示例:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div id="app">
|
||||
<h2>Pagination</h2>
|
||||
<div class="tag-list" v-if="tagsPage">
|
||||
<div class="tag-list-item" v-for="tag in tagsPage.tags">
|
||||
{{ tag.id }} - {{ tag.label }} - {{ tag.type }}
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button v-if="showMoreEnabled" @click="showMore">Show more</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const pageSize = 10
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
data: () => ({
|
||||
page: 0,
|
||||
showMoreEnabled: true,
|
||||
}),
|
||||
apollo: {
|
||||
// Pages
|
||||
tagsPage: {
|
||||
// GraphQL 查询
|
||||
query: gql`query tagsPage ($page: Int!, $pageSize: Int!) {
|
||||
tagsPage(page: $page, size: $pageSize) {
|
||||
tags {
|
||||
id
|
||||
label
|
||||
type
|
||||
}
|
||||
hasMore
|
||||
}
|
||||
}`,
|
||||
// 初始变量
|
||||
variables: {
|
||||
page: 0,
|
||||
pageSize,
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
showMore() {
|
||||
this.page ++
|
||||
// 获取更多数据并转换原始结果
|
||||
this.$apollo.queries.tagsPage.fetchMore({
|
||||
// 新的变量
|
||||
variables: {
|
||||
page: this.page,
|
||||
pageSize,
|
||||
},
|
||||
// 用新数据转换之前的结果
|
||||
updateQuery: (previousResult, { fetchMoreResult }) => {
|
||||
const newTags = fetchMoreResult.tagsPage.tags
|
||||
const hasMore = fetchMoreResult.tagsPage.hasMore
|
||||
|
||||
this.showMoreEnabled = hasMore
|
||||
|
||||
return {
|
||||
tagsPage: {
|
||||
__typename: previousResult.tagsPage.__typename,
|
||||
// 合并标签列表
|
||||
tags: [...previousResult.tagsPage.tags, ...newTags],
|
||||
hasMore,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
@@ -0,0 +1,401 @@
|
||||
# 查询
|
||||
|
||||
为每个你需要通过 Apollo 的查询结果提供数据的 Vue 属性,在 `apollo` 对象中添加一个对应属性。每一个属性都将创建一个智能查询。
|
||||
|
||||
## 简单查询
|
||||
|
||||
使用 `gql` 编写你的 GraphQL 查询:
|
||||
|
||||
```js
|
||||
import gql from 'graphql-tag'
|
||||
```
|
||||
|
||||
直接将 [gql](https://github.com/apollographql/graphql-tag) 查询作为值:
|
||||
|
||||
```js
|
||||
apollo: {
|
||||
// 简单的查询,将更新 'hello' 这个 vue 属性
|
||||
hello: gql`{hello}`,
|
||||
},
|
||||
```
|
||||
|
||||
接下来你可以通过 `this.$apollo.queries.<name>` 访问这个查询。
|
||||
|
||||
你可以在 vue 组件的 `data` 钩子中初始化属性:
|
||||
|
||||
```js
|
||||
data () {
|
||||
return {
|
||||
// 初始化你的 apollo 数据
|
||||
hello: '',
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
在服务端添加相应的 schema 和解析器:
|
||||
|
||||
```js
|
||||
export const schema = `
|
||||
type Query {
|
||||
hello: String
|
||||
}
|
||||
|
||||
schema {
|
||||
query: Query
|
||||
}
|
||||
`
|
||||
|
||||
export const resolvers = {
|
||||
Query: {
|
||||
hello(root, args, context) {
|
||||
return "Hello world!"
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
更多信息请访问 [apollo 文档](https://www.apollographql.com/docs/apollo-server/)。
|
||||
|
||||
接下来你可以在 vue 组件中正常使用属性:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="apollo">
|
||||
<h3>Hello</h3>
|
||||
<p>
|
||||
{{hello}}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
## 带参数的查询
|
||||
|
||||
你可以通过在对象中声明 `query` 和 `variables` 将变量(读取参数)添加到 `gql` 查询中:
|
||||
|
||||
```js
|
||||
// Apollo 具体选项
|
||||
apollo: {
|
||||
// 带参数的查询
|
||||
ping: {
|
||||
// gql 查询
|
||||
query: gql`query PingMessage($message: String!) {
|
||||
ping(message: $message)
|
||||
}`,
|
||||
// 静态参数
|
||||
variables: {
|
||||
message: 'Meow',
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
你可以在这个对象中使用 apollo 的 `watchQuery` 中的选项,比如:
|
||||
- `fetchPolicy`
|
||||
- `pollInterval`
|
||||
- ...
|
||||
|
||||
更多细节请查看 [apollo 文档](https://www.apollographql.com/docs/react/api/apollo-client.html#ApolloClient.watchQuery)。
|
||||
|
||||
例如,你可以像这样添加 `fetchPolicy` apollo 选项:
|
||||
|
||||
```js
|
||||
apollo: {
|
||||
// 带参数的查询
|
||||
ping: {
|
||||
query: gql`query PingMessage($message: String!) {
|
||||
ping(message: $message)
|
||||
}`,
|
||||
variables: {
|
||||
message: 'Meow'
|
||||
},
|
||||
// 在这里加入其他选项
|
||||
fetchPolicy: 'cache-and-network',
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
同样的,你可以在 vue 组件中初始化属性:
|
||||
|
||||
```js
|
||||
data () {
|
||||
return {
|
||||
// 初始化你的 apollo 数据
|
||||
ping: '',
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
在服务端添加相应的 schema 和解析器:
|
||||
|
||||
```js
|
||||
export const schema = `
|
||||
type Query {
|
||||
ping(message: String!): String
|
||||
}
|
||||
|
||||
schema {
|
||||
query: Query
|
||||
}
|
||||
`
|
||||
|
||||
export const resolvers = {
|
||||
Query: {
|
||||
ping(root, { message }, context) {
|
||||
return `Answering ${message}`
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
然后在你的 vue 组件中使用它:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="apollo">
|
||||
<h3>Ping</h3>
|
||||
<p>
|
||||
{{ ping }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
## 加载状态
|
||||
|
||||
你可以通过 `$apollo.loading` 属性显示加载状态:
|
||||
|
||||
```vue
|
||||
<div v-if="$apollo.loading">Loading...</div>
|
||||
```
|
||||
|
||||
或者针对这个特定的 `ping` 查询:
|
||||
|
||||
```vue
|
||||
<div v-if="$apollo.queries.ping.loading">Loading...</div>
|
||||
```
|
||||
|
||||
## 用函数作为选项
|
||||
|
||||
你可以使用将在创建组件时被调用一次的函数,并且它必须返回选项对象:
|
||||
|
||||
```js
|
||||
// Apollo 具体选项
|
||||
apollo: {
|
||||
// 带参数的查询
|
||||
ping () {
|
||||
// 它将在创建组件时被调用一次
|
||||
// 必须返回选项对象
|
||||
return {
|
||||
// gql 查询
|
||||
query: gql`query PingMessage($message: String!) {
|
||||
ping(message: $message)
|
||||
}`,
|
||||
// 静态参数
|
||||
variables: {
|
||||
message: 'Meow',
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
::: tip
|
||||
同样适用于 [订阅](./subscriptions.md)。
|
||||
:::
|
||||
|
||||
## 响应式查询定义
|
||||
|
||||
你可以使用函数定义 `query` 选项。这将自动更新 graphql 查询的定义:
|
||||
|
||||
```js
|
||||
// 特定标签可以是随机标签或最后添加的标签
|
||||
featuredTag: {
|
||||
query () {
|
||||
// 这里你可以用'this' 访问组件实例
|
||||
if (this.showTag === 'random') {
|
||||
return gql`{
|
||||
randomTag {
|
||||
id
|
||||
label
|
||||
type
|
||||
}
|
||||
}`
|
||||
} else if (this.showTag === 'last') {
|
||||
return gql`{
|
||||
lastTag {
|
||||
id
|
||||
label
|
||||
type
|
||||
}
|
||||
}`
|
||||
}
|
||||
},
|
||||
// 为 'featuredTag' 这个组件属性赋值
|
||||
update: data => data.randomTag || data.lastTag,
|
||||
},
|
||||
```
|
||||
|
||||
::: tip
|
||||
同样适用于 [订阅](./subscriptions.md)。
|
||||
:::
|
||||
|
||||
## 响应式参数
|
||||
|
||||
使用函数使 vue 属性能够响应式的提供给参数:
|
||||
|
||||
```js
|
||||
// Apollo 具体选项
|
||||
apollo: {
|
||||
// 带参数的查询
|
||||
ping: {
|
||||
query: gql`query PingMessage($message: String!) {
|
||||
ping(message: $message)
|
||||
}`,
|
||||
// 响应式参数
|
||||
variables() {
|
||||
// 在这里使用 vue 响应式属性
|
||||
return {
|
||||
message: this.pingInput,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
在每次参数更改时,将重新获取查询,例如:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="apollo">
|
||||
<h3>Ping</h3>
|
||||
<input v-model="pingInput" placeholder="Enter a message" />
|
||||
<p>
|
||||
{{ping}}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
## 跳过查询
|
||||
|
||||
如果查询被跳过,它将被禁用且结果将不再被更新。你可以使用 `skip` 选项:
|
||||
|
||||
```js
|
||||
// Apollo 具体选项
|
||||
apollo: {
|
||||
tags: {
|
||||
// GraphQL 查询
|
||||
query: gql`query tagList ($type: String!) {
|
||||
tags(type: $type) {
|
||||
id
|
||||
label
|
||||
}
|
||||
}`,
|
||||
// 响应式变量
|
||||
variables() {
|
||||
return {
|
||||
type: this.type,
|
||||
}
|
||||
},
|
||||
// 禁用这个查询
|
||||
skip() {
|
||||
return this.skipQuery
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
在这里,当 `skipQuery` 组件属性改变时,`skip` 将被自动调用。
|
||||
|
||||
你也可以直接访问查询并设置 `skip` 属性:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.tags.skip = true
|
||||
```
|
||||
|
||||
## 响应式查询示例
|
||||
|
||||
这里是一个使用轮询的响应式查询示例:
|
||||
|
||||
```js
|
||||
// Apollo 具体选项
|
||||
apollo: {
|
||||
// vue 实例上的 'tags' 数据属性
|
||||
tags: {
|
||||
query: gql`query tagList {
|
||||
tags {
|
||||
id,
|
||||
label
|
||||
}
|
||||
}`,
|
||||
pollInterval: 300, // 毫秒
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
这里是服务端的定义:
|
||||
|
||||
```js
|
||||
export const schema = `
|
||||
type Tag {
|
||||
id: Int
|
||||
label: String
|
||||
}
|
||||
|
||||
type Query {
|
||||
tags: [Tag]
|
||||
}
|
||||
|
||||
schema {
|
||||
query: Query
|
||||
}
|
||||
`
|
||||
|
||||
// 假数据生成器
|
||||
import casual from 'casual'
|
||||
|
||||
// 生成一些标签
|
||||
var id = 0
|
||||
var tags = []
|
||||
for (let i = 0; i < 42; i++) {
|
||||
addTag(casual.word)
|
||||
}
|
||||
|
||||
function addTag(label) {
|
||||
let t = {
|
||||
id: id++,
|
||||
label,
|
||||
}
|
||||
tags.push(t)
|
||||
return t
|
||||
}
|
||||
|
||||
export const resolvers = {
|
||||
Query: {
|
||||
tags(root, args, context) {
|
||||
return tags
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 手动添加智能查询
|
||||
|
||||
你可以使用 `$apollo.addSmartQuery(key, options)` 方法手动添加智能查询:
|
||||
|
||||
```js
|
||||
created () {
|
||||
this.$apollo.addSmartQuery('comments', {
|
||||
// 选项同上文
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
组件 `apollo` 选项中的每个查询入口都在内部调用此方法。
|
||||
:::
|
||||
|
||||
## 高级选项
|
||||
|
||||
还有更多专用于 vue-apollo 的选项,请查看 [API 参考](../../api/smart-query.md)。
|
||||
@@ -0,0 +1,310 @@
|
||||
# 订阅
|
||||
|
||||
## 设置
|
||||
|
||||
*关于服务端实现,你可以看看 [这个简单的示例](https://github.com/Akryum/apollo-server-example)。*
|
||||
|
||||
要启用基于 websocket 的订阅,需要做一些额外的设置:
|
||||
|
||||
```
|
||||
npm install --save apollo-link-ws apollo-utilities
|
||||
```
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import { ApolloClient } from 'apollo-client'
|
||||
import { HttpLink } from 'apollo-link-http'
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
// 新的引入文件
|
||||
import { split } from 'apollo-link'
|
||||
import { WebSocketLink } from 'apollo-link-ws'
|
||||
import { getMainDefinition } from 'apollo-utilities'
|
||||
|
||||
import VueApollo from 'vue-apollo'
|
||||
|
||||
const httpLink = new HttpLink({
|
||||
// 你需要在这里使用绝对路径
|
||||
uri: 'http://localhost:3020/graphql',
|
||||
})
|
||||
|
||||
// 创建订阅的 websocket 连接
|
||||
const wsLink = new WebSocketLink({
|
||||
uri: 'ws://localhost:3000/subscriptions',
|
||||
options: {
|
||||
reconnect: true,
|
||||
},
|
||||
})
|
||||
|
||||
// 使用分割连接的功能
|
||||
// 你可以根据发送的操作类型将数据发送到不同的连接
|
||||
const link = split(
|
||||
// 根据操作类型分割
|
||||
({ query }) => {
|
||||
const { kind, operation } = getMainDefinition(query)
|
||||
return kind === 'OperationDefinition' &&
|
||||
operation === 'subscription'
|
||||
},
|
||||
wsLink,
|
||||
httpLink
|
||||
)
|
||||
|
||||
// 创建 apollo 客户端
|
||||
const apolloClient = new ApolloClient({
|
||||
link,
|
||||
cache: new InMemoryCache(),
|
||||
connectToDevTools: true,
|
||||
})
|
||||
|
||||
// 像之前一样安装 vue 插件
|
||||
Vue.use(VueApollo)
|
||||
```
|
||||
|
||||
## 订阅更多
|
||||
|
||||
如果你需要更新一个来自订阅的查询结果,最好的方式是使用 `subscribeToMore` 查询方法。它将创建链接到查询的 [智能订阅](../../api/smart-subscription.md)。你只需要将 `subscribeToMore` 添加到查询中:
|
||||
|
||||
```js
|
||||
apollo: {
|
||||
tags: {
|
||||
query: TAGS_QUERY,
|
||||
subscribeToMore: {
|
||||
document: gql`subscription name($param: String!) {
|
||||
itemAdded(param: $param) {
|
||||
id
|
||||
label
|
||||
}
|
||||
}`,
|
||||
// 传递给订阅的变量
|
||||
// 由于我们使用了函数,因此它们是响应式的
|
||||
variables () {
|
||||
return {
|
||||
param: this.param,
|
||||
}
|
||||
},
|
||||
// 变更之前的结果
|
||||
updateQuery: (previousResult, { subscriptionData }) => {
|
||||
// 在这里用之前的结果和新数据组合成新的结果
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
注意,你可以将一组订阅传递给 `subscribeToMore` 以将此查询关联到多个订阅。
|
||||
:::
|
||||
|
||||
### Alternate usage
|
||||
|
||||
你可以使用 `this.$apollo.queries.<name>` 访问你在 `apollo` 选项中定义的查询,所以它看起来像这样:
|
||||
|
||||
```js
|
||||
this.$apollo.queries.tags.subscribeToMore({
|
||||
// GraphQL 文档
|
||||
document: gql`subscription name($param: String!) {
|
||||
itemAdded(param: $param) {
|
||||
id
|
||||
label
|
||||
}
|
||||
}`,
|
||||
// 传递给订阅的变量
|
||||
variables: {
|
||||
param: '42',
|
||||
},
|
||||
// 变更之前的结果
|
||||
updateQuery: (previousResult, { subscriptionData }) => {
|
||||
// 在这里用之前的结果和新数据组合成新的结果
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
如果相关查询停止,订阅将自动销毁。
|
||||
|
||||
这里是一个示例:
|
||||
|
||||
```js
|
||||
// 订阅的 GraphQL 文档
|
||||
const TAG_ADDED = gql`subscription tags($type: String!) {
|
||||
tagAdded(type: $type) {
|
||||
id
|
||||
label
|
||||
type
|
||||
}
|
||||
}`
|
||||
|
||||
// SubscribeToMore 标签
|
||||
// 我们有不同类型的标签
|
||||
// 每种类型都有一个订阅 '频道'
|
||||
this.$watch(() => this.type, (type, oldType) => {
|
||||
if (type !== oldType || !this.tagsSub) {
|
||||
// 我们需要在重新订阅之前取消订阅
|
||||
if (this.tagsSub) {
|
||||
this.tagsSub.unsubscribe()
|
||||
}
|
||||
// 在查询上订阅
|
||||
this.tagsSub = this.$apollo.queries.tags.subscribeToMore({
|
||||
document: TAG_ADDED,
|
||||
variables: {
|
||||
type,
|
||||
},
|
||||
// 变更之前的结果
|
||||
updateQuery: (previousResult, { subscriptionData }) => {
|
||||
// 如果我们在没有做操作的情况下已经添加了标签
|
||||
// 这可能是由 addTag 变更上的 `updateQuery` 导致
|
||||
if (previousResult.tags.find(tag => tag.id === subscriptionData.data.tagAdded.id)) {
|
||||
return previousResult
|
||||
}
|
||||
|
||||
return {
|
||||
tags: [
|
||||
...previousResult.tags,
|
||||
// 添加新的标签
|
||||
subscriptionData.data.tagAdded,
|
||||
],
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
})
|
||||
```
|
||||
|
||||
## 简单订阅
|
||||
|
||||
::: danger
|
||||
如果要使用订阅的结果更新查询,请使用 `subscribeToMore`。
|
||||
以下的方法适用于 'notify' 用例
|
||||
:::
|
||||
|
||||
你可以在 `apollo` 选项中使用 `$subscribe` 关键字来声明 [智能订阅](../../api/smart-subscription.md):
|
||||
|
||||
```js
|
||||
apollo: {
|
||||
// 订阅
|
||||
$subscribe: {
|
||||
// 当添加一个标签时
|
||||
tagAdded: {
|
||||
query: gql`subscription tags($type: String!) {
|
||||
tagAdded(type: $type) {
|
||||
id
|
||||
label
|
||||
type
|
||||
}
|
||||
}`,
|
||||
// 响应式变量
|
||||
variables() {
|
||||
// 像常规查询一样运作
|
||||
// 在每次改变值时都会使用正确的变量重新订阅
|
||||
return {
|
||||
type: this.type,
|
||||
}
|
||||
},
|
||||
// 结果钩子
|
||||
result(data) {
|
||||
console.log(data)
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
你可以使用 `this.$apollo.subscriptions.<name>` 访问这个订阅。
|
||||
|
||||
:::tip
|
||||
和查询一样,你可以 [使用函数](./queries.md#option-function) 声明订阅,并且可以 [使用响应式函数](./queries.md#reactive-query-definition) 声明 `query` 选项。
|
||||
:::
|
||||
|
||||
## 跳过订阅
|
||||
|
||||
如果订阅被跳过,它将被禁用且不再被更新。你可以使用 `skip` 选项:
|
||||
|
||||
```js
|
||||
// Apollo 具体选项
|
||||
apollo: {
|
||||
// 订阅
|
||||
$subscribe: {
|
||||
// 当添加一个标签时
|
||||
tags: {
|
||||
query: gql`subscription tags($type: String!) {
|
||||
tagAdded(type: $type) {
|
||||
id
|
||||
label
|
||||
type
|
||||
}
|
||||
}`,
|
||||
// 响应式变量
|
||||
variables() {
|
||||
return {
|
||||
type: this.type,
|
||||
}
|
||||
},
|
||||
// 结果钩子
|
||||
result(data) {
|
||||
// 更新本地数据
|
||||
this.tags.push(data.tagAdded)
|
||||
},
|
||||
// 跳过这个订阅
|
||||
skip() {
|
||||
return this.skipSubscription
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
在这里,当 `skipSubscription` 组件属性改变时,`skip` 将被自动调用。
|
||||
|
||||
你也可以直接访问订阅并设置 `skip` 属性:
|
||||
|
||||
```js
|
||||
this.$apollo.subscriptions.tags.skip = true
|
||||
```
|
||||
|
||||
## 手动添加智能订阅
|
||||
|
||||
你可以使用 `$apollo.addSmartSubscription(key, options)` 方法手动添加智能订阅:
|
||||
|
||||
```js
|
||||
created () {
|
||||
this.$apollo.addSmartSubscription('tagAdded', {
|
||||
// 选项同 '$subscribe'
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
:::tip
|
||||
组件 `apollo` 选项中的每个 `$subscribe` 对象入口都在内部调用此方法。
|
||||
:::
|
||||
|
||||
## 标准 Apollo 订阅
|
||||
|
||||
使用 `$apollo.subscribe()` 方法来创建一个 GraphQL 订阅,当组件被销毁时将自动终止。它**不会**创建智能订阅。
|
||||
|
||||
```js
|
||||
mounted() {
|
||||
const subQuery = gql`subscription tags($type: String!) {
|
||||
tagAdded(type: $type) {
|
||||
id
|
||||
label
|
||||
type
|
||||
}
|
||||
}`
|
||||
|
||||
const observer = this.$apollo.subscribe({
|
||||
query: subQuery,
|
||||
variables: {
|
||||
type: 'City',
|
||||
},
|
||||
})
|
||||
|
||||
observer.subscribe({
|
||||
next(data) {
|
||||
console.log(data)
|
||||
},
|
||||
error(error) {
|
||||
console.error(error)
|
||||
},
|
||||
})
|
||||
},
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
# 什么是 Apollo 组件?
|
||||
|
||||
这些组件就像其他组件一样。它们在 prop 中使用 GraphQL 文档,并使用 [作用域插槽功能](https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots) 来传递结果。
|
||||
|
||||
这样做的好处是你可以直接在模板中使用这些组件,而不是使用组件的 `apollo` 选项。在某些情况下,你甚至不需要在 `.vue` 中添加脚本部分!这种代码会更加声明式。
|
||||
|
||||
这是一个简单的例子:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="users-list">
|
||||
<!-- Apollo 查询 -->
|
||||
<ApolloQuery :query="require('@/graphql/users.gql')">
|
||||
<!-- 结果将自动更新 -->
|
||||
<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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 不需要脚本 -->
|
||||
|
||||
<style scoped>
|
||||
.user {
|
||||
list-style: none;
|
||||
padding: 12px;
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
@@ -0,0 +1,23 @@
|
||||
# ApolloMutation
|
||||
|
||||
你可以使用 `ApolloMutation`(或 `apollo-mutation`)组件直接在模板中调用 Apollo 变更。
|
||||
|
||||
这是一个简单的例子:
|
||||
|
||||
```vue
|
||||
<ApolloMutation
|
||||
:mutation="require('@/graphql/userLogin.gql')"
|
||||
:variables="{
|
||||
email,
|
||||
password,
|
||||
}"
|
||||
@done="onDone"
|
||||
>
|
||||
<template slot-scope="{ mutate, loading, error }">
|
||||
<button :disabled="loading" @click="mutate()">Click me</button>
|
||||
<p v-if="error">An error occured: {{ error }}</p>
|
||||
</template>
|
||||
</ApolloMutation>
|
||||
```
|
||||
|
||||
更多参见 [API 参考](../../api/apollo-mutation.md).
|
||||
@@ -0,0 +1,28 @@
|
||||
# ApolloQuery
|
||||
|
||||
你可以使用 `ApolloQuery`(或 `apollo-query`)组件直接在模板中侦听 Apollo 查询。
|
||||
|
||||
这是一个简单的例子:
|
||||
|
||||
```vue
|
||||
<ApolloQuery
|
||||
:query="require('../graphql/HelloWorld.gql')"
|
||||
:variables="{ name }"
|
||||
>
|
||||
<template slot-scope="{ result: { loading, error, data } }">
|
||||
<!-- Loading -->
|
||||
<div v-if="loading" class="loading apollo">Loading...</div>
|
||||
|
||||
<!-- Error -->
|
||||
<div v-else-if="error" class="error apollo">An error occured</div>
|
||||
|
||||
<!-- Result -->
|
||||
<div v-else-if="data" class="result apollo">{{ data.hello }}</div>
|
||||
|
||||
<!-- No result -->
|
||||
<div v-else class="no-result apollo">No result :(</div>
|
||||
</template>
|
||||
</ApolloQuery>
|
||||
```
|
||||
|
||||
更多参见 [API 参考](../../api/apollo-query.md).
|
||||
@@ -0,0 +1,88 @@
|
||||
# ApolloSubscribeToMore
|
||||
|
||||
你可以使用 `ApolloSubscribeToMore`(或 `apollo-subscribe-to-more`)组件订阅更多数据。你可以在一个 `<ApolloQuery>` 组件中放置任意数量的订阅组件。
|
||||
|
||||
::: tip
|
||||
如果更新关联到现有对象(例如更改某个字段的值),则不需要 `updateQuery`,因为 Apollo 客户端能够自动更新缓存。
|
||||
:::
|
||||
|
||||
这是一个简单的例子:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<ApolloQuery :query="...">
|
||||
<ApolloSubscribeToMore
|
||||
:document="require('../gql/MessageAdded.gql')"
|
||||
:variables="{ channel }"
|
||||
:updateQuery="onMessageAdded"
|
||||
/>
|
||||
|
||||
<!-- ... -->
|
||||
</ApolloQuery>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
channel: 'general',
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onMessageAdded (previousResult, { subscriptionData }) {
|
||||
// 之前的结果是不可变的
|
||||
const newResult = {
|
||||
messages: [...previousResult.messages],
|
||||
}
|
||||
// 添加问题到列表中
|
||||
newResult.messages.push(subscriptionData.data.messageAdded)
|
||||
return newResult
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
更多参见 [API 参考](../../api/apollo-subscribe-to-more.md).
|
||||
|
||||
## `updateQuery` 的示例
|
||||
|
||||
将新项添加到缓存中:
|
||||
|
||||
```js
|
||||
methods: {
|
||||
onMessageAdded (previousResult, { subscriptionData }) {
|
||||
// 之前的结果是不可变的
|
||||
const newResult = {
|
||||
messages: [...previousResult.messages],
|
||||
}
|
||||
// 添加问题到列表中
|
||||
newResult.messages.push(subscriptionData.data.messageAdded)
|
||||
return newResult
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
从缓存中删除一项:
|
||||
|
||||
```js
|
||||
methods: {
|
||||
onMessageAdded (previousResult, { subscriptionData }) {
|
||||
const removedMessage = subscriptionData.data.messageRemoved
|
||||
const index = previousResult.messages.findIndex(
|
||||
m => m.id === removedMessage.id
|
||||
)
|
||||
|
||||
if (index === -1) return previousResult
|
||||
|
||||
// 之前的结果是不可变的
|
||||
const newResult = {
|
||||
messages: [...previousResult.messages],
|
||||
}
|
||||
// 从列表中移除问题
|
||||
newResult.messages.splice(index, 1)
|
||||
return newResult
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,108 @@
|
||||
# 安装
|
||||
|
||||
## Vue CLI Plugin
|
||||
|
||||
我为 [vue-cli](http://cli.vuejs.org) 制作了一个插件,因此仅用两分钟你就可以添加 Apollo(附带一个可选的 GraphQL 服务器)!✨🚀
|
||||
|
||||
在你的 vue-cli 3 项目中:
|
||||
|
||||
```bash
|
||||
vue add apollo
|
||||
```
|
||||
|
||||
然后你可以跳到下一部分:[基本用法](./apollo/)。
|
||||
|
||||
[更多信息](https://github.com/Akryum/vue-cli-plugin-apollo)
|
||||
|
||||
## Apollo Boost
|
||||
|
||||
Apollo Boost 是一种零配置开始使用 Apollo Client 的方式。它包含一些实用的默认值,例如我们推荐的 `InMemoryCache` 和 `HttpLink`,它非常适合用于快速启动开发:
|
||||
|
||||
安装:
|
||||
|
||||
```
|
||||
npm install --save vue-apollo graphql apollo-boost
|
||||
```
|
||||
|
||||
或:
|
||||
|
||||
```
|
||||
yarn add vue-apollo graphql apollo-boost
|
||||
```
|
||||
|
||||
### Apollo client
|
||||
|
||||
在你的应用中创建一个 `ApolloClient` 实例并安装 `VueApollo` 插件:
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import ApolloClient from "apollo-boost"
|
||||
import VueApollo from "vue-apollo"
|
||||
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: new ApolloClient({
|
||||
uri: "https://api.graphcms.com/simple/v1/awesomeTalksClone"
|
||||
})
|
||||
})
|
||||
|
||||
Vue.use(VueApollo)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 手动操作
|
||||
|
||||
如果你想要更细的粒度控制,尝试在服务器端配置之前安装这些包,并且将 apollo 添加到 meteor.js 中。
|
||||
|
||||
```
|
||||
npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
|
||||
```
|
||||
|
||||
或:
|
||||
|
||||
```
|
||||
yarn add vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
|
||||
```
|
||||
|
||||
### Apollo 客户端
|
||||
|
||||
在你的应用中创建一个 `ApolloClient` 实例并安装 `VueApollo` 插件:
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import { ApolloClient } from 'apollo-client'
|
||||
import { HttpLink } from 'apollo-link-http'
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
import VueApollo from 'vue-apollo'
|
||||
|
||||
const httpLink = new HttpLink({
|
||||
// 你需要在这里使用绝对路径
|
||||
uri: 'http://localhost:3020/graphql',
|
||||
})
|
||||
|
||||
// 创建 apollo 客户端
|
||||
const apolloClient = new ApolloClient({
|
||||
link: httpLink,
|
||||
cache: new InMemoryCache(),
|
||||
connectToDevTools: true,
|
||||
})
|
||||
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: apolloClient,
|
||||
})
|
||||
|
||||
// 安装 vue 插件
|
||||
Vue.use(VueApollo)
|
||||
```
|
||||
|
||||
## Apollo provider
|
||||
|
||||
Provider 保存了可以在接下来被所有子组件使用的 Apollo 客户端实例。通过 `provide` 属性将它注入你的组件:
|
||||
|
||||
```js
|
||||
new Vue({
|
||||
el: '#app',
|
||||
apolloProvider,
|
||||
render: h => h(App),
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
# 本地状态
|
||||
|
||||
如果你需要管理本地数据,你可以使用 [apollo-link-state](https://github.com/apollographql/apollo-link-state) 和 `@client` 指令来实现:
|
||||
|
||||
```js
|
||||
export default {
|
||||
apollo: {
|
||||
hello: gql`
|
||||
query {
|
||||
hello @client {
|
||||
msg
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
mounted() {
|
||||
// 变更 hello 消息
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: gql`
|
||||
mutation($msg: String!) {
|
||||
updateHello(message: $msg) @client
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
msg: 'hello from link-state!'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[示例项目](https://codesandbox.io/s/zqqj82396p) (感谢 @chriswingler)
|
||||
|
||||
[Todo App](https://codesandbox.io/s/x2jr96r8pp) (感谢 @NikkitaFTW)
|
||||
|
||||
---
|
||||
@@ -0,0 +1,32 @@
|
||||
# 多客户端
|
||||
|
||||
如果你的应用需要连接到不同的 GraphQL 入口端点,你可以指定多个 apollo 客户端:
|
||||
|
||||
```js
|
||||
const apolloProvider = new VueApollo({
|
||||
clients: {
|
||||
a: apolloClient,
|
||||
b: otherApolloClient,
|
||||
},
|
||||
defaultClient: apolloClient,
|
||||
})
|
||||
```
|
||||
|
||||
在组件的 `apollo` 选项中,你可以使用 `$client` 为所有的查询、订阅和变更定义要使用的客户端(仅限在此组件内):
|
||||
|
||||
```js
|
||||
export default {
|
||||
apollo: {
|
||||
$client: 'b',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
你也可以在单个查询,订阅和变更的选项中使用 `client` 属性来指定客户端:
|
||||
|
||||
```js
|
||||
tags: {
|
||||
query: gql`...`,
|
||||
client: 'b',
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,362 @@
|
||||
# 服务端渲染
|
||||
|
||||
## Vue CLI 插件
|
||||
|
||||
我为 [vue-cli](http://cli.vuejs.org) 制作了一个插件,因此仅用两分钟你就可以将你的 vue-apollo 应用转换为同构 SSR 应用!✨🚀
|
||||
|
||||
在你的 vue-cli 3 项目中:
|
||||
|
||||
```bash
|
||||
vue add @akryum/ssr
|
||||
```
|
||||
|
||||
[更多信息](https://github.com/Akryum/vue-cli-plugin-ssr)
|
||||
|
||||
## 预取组件
|
||||
|
||||
在要在服务端预取的查询上,添加 `prefetch` 选项。它可以是:
|
||||
- 一个变量对象;
|
||||
- 一个获取上下文对象(例如可以包含 URL)并返回一个变量对象的函数;
|
||||
- `false` 禁用此查询的预取。
|
||||
|
||||
如果你在 `prefetch` 选项中返回一个变量对象,请确保它与 `variables` 选项的结果相匹配。如果它们不匹配,则在服务端渲染模板时,查询的数据属性将不会被填充。
|
||||
|
||||
::: danger
|
||||
在服务端进行预取时,你无法访问组件实例。
|
||||
:::
|
||||
|
||||
示例:
|
||||
|
||||
```js
|
||||
export default {
|
||||
apollo: {
|
||||
allPosts: {
|
||||
// 此查询将被预取
|
||||
query: gql`query AllPosts {
|
||||
allPosts {
|
||||
id
|
||||
imageUrl
|
||||
description
|
||||
}
|
||||
}`,
|
||||
prefetch: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
示例 2:
|
||||
|
||||
```js
|
||||
export default {
|
||||
apollo: {
|
||||
post: {
|
||||
query: gql`query Post($id: ID!) {
|
||||
post (id: $id) {
|
||||
id
|
||||
imageUrl
|
||||
description
|
||||
}
|
||||
}`,
|
||||
prefetch: ({ route }) => {
|
||||
return {
|
||||
id: route.params.id,
|
||||
}
|
||||
},
|
||||
variables () {
|
||||
return {
|
||||
id: this.id,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 跳过预取
|
||||
|
||||
不预取查询的示例:
|
||||
|
||||
```js
|
||||
export default {
|
||||
apollo: {
|
||||
allPosts: {
|
||||
query: gql`query AllPosts {
|
||||
allPosts {}
|
||||
id
|
||||
imageUrl
|
||||
description
|
||||
}
|
||||
}`,
|
||||
// 不要预取
|
||||
prefetch: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如果要跳过特定组件的所有查询的预取,使用 `$prefetch` 选项:
|
||||
|
||||
```js
|
||||
export default {
|
||||
apollo: {
|
||||
// 不要预取任何查询
|
||||
$prefetch: false,
|
||||
allPosts: {
|
||||
query: gql`query AllPosts {
|
||||
allPosts {
|
||||
id
|
||||
imageUrl
|
||||
description
|
||||
}
|
||||
}`,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你也可以在任何组件上放置一个 `no-prefetch` 属性,以便在遍历树收集 Apollo 查询时忽略它:
|
||||
|
||||
```vue
|
||||
<ApolloQuery no-prefetch>
|
||||
```
|
||||
|
||||
## 在服务端
|
||||
|
||||
在服务端入口中,你需要在 Vue 中安装 `ApolloSSR` 插件:
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import ApolloSSR from 'vue-apollo/ssr'
|
||||
|
||||
Vue.use(ApolloSSR)
|
||||
```
|
||||
|
||||
使用 `ApolloSSR.prefetchAll` 方法来预取你已标记的所有 apollo 查询。第一个参数是 `apolloProvider`。第二个参数是要包含的组件定义数组(例如来自 `router.getMatchedComponents` 方法)。第三个参数是传递给 `prefetch` 钩子的上下文对象(参见上文),建议传入 vue-router 的 `currentRoute` 对象。当所有的 apollo 查询都被加载时,它返回已解决的(resolved) promise。
|
||||
|
||||
以下是一个使用了 vue-router 和 Vuex store 的示例:
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import ApolloSSR from 'vue-apollo/ssr'
|
||||
import App from './App.vue'
|
||||
|
||||
Vue.use(ApolloSSR)
|
||||
|
||||
export default () => new Promise((resolve, reject) => {
|
||||
const { app, router, store, apolloProvider } = CreateApp({
|
||||
ssr: true,
|
||||
})
|
||||
|
||||
// 设置 router 的位置
|
||||
router.push(context.url)
|
||||
|
||||
// 等待 router 解析完可能的异步钩子
|
||||
router.onReady(() => {
|
||||
const matchedComponents = router.getMatchedComponents()
|
||||
|
||||
// 匹配不到的路由
|
||||
if (!matchedComponents.length) {
|
||||
reject({ code: 404 })
|
||||
}
|
||||
|
||||
let js = ''
|
||||
|
||||
// 调用匹配到路由的组件的预取钩子
|
||||
// 每个 preFetch 钩子分配到一个 store action 并返回一个 Promise
|
||||
// 当 action 操作完成且 store 状态已更新时解析这个 Promise
|
||||
|
||||
// Vuex Store 预取
|
||||
Promise.all(matchedComponents.map(component => {
|
||||
return component.asyncData && component.asyncData({
|
||||
store,
|
||||
route: router.currentRoute,
|
||||
})
|
||||
})
|
||||
// Apollo 预取
|
||||
// 这里将预取整个应用中的所有 Apollo 查询
|
||||
.then(() => ApolloSSR.prefetchAll(apolloProvider, [App, ...matchedComponents], {
|
||||
store,
|
||||
route: router.currentRoute,
|
||||
})
|
||||
.then(() => {
|
||||
// 将 Vuex 状态和 Apollo 缓存注入到页面
|
||||
// 这将防止不必要的查询
|
||||
|
||||
// Vuex
|
||||
js += `window.__INITIAL_STATE__=${JSON.stringify(store.state)};`
|
||||
|
||||
// Apollo
|
||||
js += ApolloSSR.exportStates(apolloProvider)
|
||||
|
||||
resolve({
|
||||
app,
|
||||
js,
|
||||
})
|
||||
}).catch(reject)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
使用 `ApolloSSR.exportStates(apolloProvider, options)` 方法来获取你需要注入到生成出来页面的 JavaScript 代码,这些代码用于将 apollo 缓存数据传递给客户端。
|
||||
|
||||
它需要一个 `options` 参数,默认为:
|
||||
|
||||
```js
|
||||
{
|
||||
// 全局变量名
|
||||
globalName: '__APOLLO_STATE__',
|
||||
// 变量设置到的全局对象
|
||||
attachTo: 'window',
|
||||
// 每个 apollo 客户端状态的 key 的前缀
|
||||
exportNamespace: '',
|
||||
}
|
||||
```
|
||||
|
||||
你也可以使用 `ApolloSSR.getStates(apolloProvider, options)` 方法来获取 JS 对象而不是脚本字符串。
|
||||
|
||||
它需要一个 `options` 参数,默认为:
|
||||
|
||||
```js
|
||||
{
|
||||
// 每个 apollo 客户端状态的 key 的前缀
|
||||
exportNamespace: '',
|
||||
}
|
||||
```
|
||||
|
||||
### 创建 Apollo Client
|
||||
|
||||
建议在一个带有 `ssr` 参数的函数内部创建 apollo 客户端,参数在服务端为 `true`,在客户端为 `false`。
|
||||
|
||||
这里是一个示例:
|
||||
|
||||
```js
|
||||
// src/api/apollo.js
|
||||
|
||||
import Vue from 'vue'
|
||||
import { ApolloClient } from 'apollo-client'
|
||||
import { HttpLink } from 'apollo-link-http'
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
import VueApollo from 'vue-apollo'
|
||||
|
||||
// 安装 vue 插件
|
||||
Vue.use(VueApollo)
|
||||
|
||||
// 创建 apollo 客户端
|
||||
export function createApolloClient (ssr = false) {
|
||||
const httpLink = new HttpLink({
|
||||
// 你需要在这里使用绝对路径
|
||||
uri: ENDPOINT + '/graphql',
|
||||
})
|
||||
|
||||
const cache = new InMemoryCache()
|
||||
|
||||
// 如果在客户端则恢复注入状态
|
||||
if (!ssr) {
|
||||
if (typeof window !== 'undefined') {
|
||||
const state = window.__APOLLO_STATE__
|
||||
if (state) {
|
||||
// 如果你有多个客户端,使用 `state.<client_id>`
|
||||
cache.restore(state.defaultClient)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const apolloClient = new ApolloClient({
|
||||
link: httpLink,
|
||||
cache,
|
||||
...(ssr ? {
|
||||
// 在服务端设置此选项以优化 SSR 时的查询
|
||||
ssrMode: true,
|
||||
} : {
|
||||
// 这将暂时禁用查询强制获取
|
||||
ssrForceFetchDelay: 100,
|
||||
}),
|
||||
})
|
||||
|
||||
return apolloClient
|
||||
}
|
||||
```
|
||||
|
||||
常见的 `CreateApp` 方法示例:
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Vuex from 'vuex'
|
||||
import { sync } from 'vuex-router-sync'
|
||||
|
||||
import VueApollo from 'vue-apollo'
|
||||
import { createApolloClient } from './api/apollo'
|
||||
|
||||
import App from './ui/App.vue'
|
||||
import routes from './routes'
|
||||
import storeOptions from './store'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
Vue.use(Vuex)
|
||||
|
||||
function createApp (context) {
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
routes,
|
||||
})
|
||||
|
||||
const store = new Vuex.Store(storeOptions)
|
||||
|
||||
// 同步路由到 vuex store
|
||||
// 将注册 `store.state.route`
|
||||
sync(store, router)
|
||||
|
||||
// Apollo
|
||||
const apolloClient = createApolloClient(context.ssr)
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: apolloClient,
|
||||
})
|
||||
|
||||
return {
|
||||
app: new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
apolloProvider,
|
||||
...App,
|
||||
}),
|
||||
router,
|
||||
store,
|
||||
apolloProvider,
|
||||
}
|
||||
}
|
||||
|
||||
export default createApp
|
||||
```
|
||||
|
||||
在客户端:
|
||||
|
||||
```js
|
||||
import CreateApp from './app'
|
||||
|
||||
CreateApp({
|
||||
ssr: false,
|
||||
})
|
||||
```
|
||||
|
||||
在服务端:
|
||||
|
||||
```js
|
||||
import CreateApp from './app'
|
||||
|
||||
export default () => new Promise((resolve, reject) => {
|
||||
const { app, router, store, apolloProvider } = CreateApp({
|
||||
ssr: true,
|
||||
})
|
||||
|
||||
// 设置 router 的位置
|
||||
router.push(context.url)
|
||||
|
||||
// 等待 router 解析完可能的异步钩子
|
||||
router.onReady(() => {
|
||||
// 预取,渲染 HTML(参见上文)
|
||||
})
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,152 @@
|
||||
# 测试
|
||||
|
||||
要为 vue-apollo 查询和变更创建单元测试,你可以选择简单测试或使用模拟 GraqhQL schema 进行测试。所有的示例都使用了 [Jest](https://jestjs.io/) 和 [vue-test-utils](https://github.com/vuejs/vue-test-utils)。
|
||||
|
||||
## 简单测试
|
||||
|
||||
对于简单的查询测试,你只需要设置组件数据并检查组件如何使用 Jest 快照功能进行渲染。比如说,如果你有一个展示所有 Vue 英雄的查询,你可以添加一个包含单个英雄的模拟数组:
|
||||
|
||||
```js
|
||||
test('displayed heroes correctly with query data', () => {
|
||||
const wrapper = shallowMount(App, { localVue });
|
||||
wrapper.setData({
|
||||
allHeroes: [
|
||||
{
|
||||
id: 'some-id',
|
||||
name: 'Evan You',
|
||||
image: 'https://pbs.twimg.com/profile_images/888432310504370176/mhoGA4uj_400x400.jpg',
|
||||
twitter: 'youyuxi',
|
||||
github: 'yyx990803',
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
```
|
||||
对于简单的变更测试,你需要检查组件中是否调用了 `$apollo` 的 `mutate` 方法。接下来的示例在 `addHero` 方法中调用了变更:
|
||||
|
||||
```js
|
||||
test('called Apollo mutation in addHero() method', () => {
|
||||
const mutate = jest.fn();
|
||||
const wrapper = mount(App, {
|
||||
localVue,
|
||||
mocks: {
|
||||
$apollo: {
|
||||
mutate,
|
||||
},
|
||||
},
|
||||
});
|
||||
wrapper.vm.addHero();
|
||||
expect(mutate).toBeCalled();
|
||||
});
|
||||
```
|
||||
|
||||
## 使用模拟 GraqhQL schema 进行测试
|
||||
|
||||
你还可以使用 [模拟 GraphQL schema](https://www.apollographql.com/docs/graphql-tools/mocking.html) 进行更深入、更复杂的测试。这种方法并不包含 Apollo,但能够让你检查某些查询是否能够在给定的 schema 中正确执行。
|
||||
|
||||
为此,首先需要建立 schema:
|
||||
|
||||
```js
|
||||
const sourceSchema = `
|
||||
type VueHero {
|
||||
id: ID!
|
||||
name: String!
|
||||
image: String
|
||||
github: String
|
||||
twitter: String
|
||||
}
|
||||
|
||||
input HeroInput {
|
||||
name: String!
|
||||
image: String
|
||||
github: String
|
||||
twitter: String
|
||||
}
|
||||
|
||||
|
||||
type Query {
|
||||
allHeroes: [VueHero]
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
addHero(hero: HeroInput!): VueHero!
|
||||
deleteHero(name: String!): Boolean
|
||||
}
|
||||
`;
|
||||
```
|
||||
下一步是使用 `graphql-tools` 方法创建可执行的 schema:
|
||||
|
||||
```js
|
||||
import { makeExecutableSchema } from 'graphql-tools';
|
||||
...
|
||||
const schema = makeExecutableSchema({
|
||||
typeDefs: sourceSchema,
|
||||
});
|
||||
```
|
||||
之后你需要向 schema 添加模拟函数:
|
||||
|
||||
```js
|
||||
import { addMockFunctionsToSchema } from 'graphql-tools';
|
||||
...
|
||||
addMockFunctionsToSchema({
|
||||
schema,
|
||||
});
|
||||
```
|
||||
指定 GraphQL 查询字符串:
|
||||
|
||||
```js
|
||||
const query = `
|
||||
query {
|
||||
allHeroes {
|
||||
id
|
||||
name
|
||||
twitter
|
||||
github
|
||||
image
|
||||
}
|
||||
}
|
||||
`;
|
||||
```
|
||||
在测试用例中调用 GraphQL 查询,保存响应到组件数据中,然后检查渲染完成的组件是否与快照匹配:
|
||||
|
||||
```js
|
||||
graphql(schema, query).then(result => {
|
||||
wrapper.setData(result.data);
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
```
|
||||
在这个用例中,所有字符串字段将等于 `Hello World` 且所有数值都将为负数。如果你想要获得更贴近现实的响应,则应当为某些查询指定解析器:
|
||||
|
||||
```js
|
||||
const resolvers = {
|
||||
Query: {
|
||||
allHeroes: () => [
|
||||
{
|
||||
id: '-pBE1JAyz',
|
||||
name: 'Evan You',
|
||||
image:
|
||||
'https://pbs.twimg.com/profile_images/888432310504370176/mhoGA4uj_400x400.jpg',
|
||||
twitter: 'youyuxi',
|
||||
github: 'yyx990803',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
然后你需要将解析器添加到可执行 schema,并在添加模拟函数时将 `preserveResolvers` 属性设置为 true:
|
||||
|
||||
```js
|
||||
const schema = makeExecutableSchema({
|
||||
typeDefs: sourceSchema,
|
||||
resolvers,
|
||||
});
|
||||
|
||||
addMockFunctionsToSchema({
|
||||
schema,
|
||||
preserveResolvers: true,
|
||||
});
|
||||
```
|
||||
你可以用同样的方法来测试变更。
|
||||
|
||||
---
|
||||
@@ -0,0 +1,196 @@
|
||||
# From vue-apollo 2 and Apollo 1
|
||||
|
||||
主要的变动与 apollo 客户端的设置有关。你的组件代码不应该受到影响。Apollo 现在使用更灵活的 [apollo-link](https://github.com/apollographql/apollo-link) 系统,允许将多个连接组合在一起以添加更多功能(如批处理,离线支持等)。
|
||||
|
||||
## 安装
|
||||
|
||||
### 包
|
||||
|
||||
之前:
|
||||
|
||||
```
|
||||
npm install --save vue-apollo apollo-client
|
||||
```
|
||||
|
||||
之后:
|
||||
|
||||
```
|
||||
npm install --save vue-apollo@next graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
|
||||
```
|
||||
|
||||
### 导入
|
||||
|
||||
之前:
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import { ApolloClient, createBatchingNetworkInterface } from 'apollo-client'
|
||||
import VueApollo from 'vue-apollo'
|
||||
```
|
||||
|
||||
之后:
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import { ApolloClient } from 'apollo-client'
|
||||
import { HttpLink } from 'apollo-link-http'
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
import VueApollo from 'vue-apollo'
|
||||
```
|
||||
|
||||
### Apollo 设置
|
||||
|
||||
之前:
|
||||
|
||||
```js
|
||||
// 创建网络接口
|
||||
const networkInterface = createNetworkInterface({
|
||||
uri: 'http://localhost:3000/graphql',
|
||||
transportBatching: true,
|
||||
})
|
||||
|
||||
// 创建订阅 websocket 客户端
|
||||
const wsClient = new SubscriptionClient('ws://localhost:3000/subscriptions', {
|
||||
reconnect: true,
|
||||
})
|
||||
|
||||
// 使用订阅客户端扩展网络接口
|
||||
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
|
||||
networkInterface,
|
||||
wsClient,
|
||||
)
|
||||
|
||||
// 用新的网络接口创建 apollo 客户端
|
||||
const apolloClient = new ApolloClient({
|
||||
networkInterface: networkInterfaceWithSubscriptions,
|
||||
connectToDevTools: true,
|
||||
})
|
||||
```
|
||||
|
||||
之后:
|
||||
|
||||
```js
|
||||
const httpLink = new HttpLink({
|
||||
// 你需要在这里使用绝对路径
|
||||
uri: 'http://localhost:3020/graphql',
|
||||
})
|
||||
|
||||
// 创建订阅 websocket 连接
|
||||
const wsLink = new WebSocketLink({
|
||||
uri: 'ws://localhost:3000/subscriptions',
|
||||
options: {
|
||||
reconnect: true,
|
||||
},
|
||||
})
|
||||
|
||||
// 使用分割连接的功能
|
||||
// 你可以根据发送的操作类型将数据发送到不同的连接
|
||||
const link = split(
|
||||
// 根据操作类型分割
|
||||
({ query }) => {
|
||||
const { kind, operation } = getMainDefinition(query)
|
||||
return kind === 'OperationDefinition' &&
|
||||
operation === 'subscription'
|
||||
},
|
||||
wsLink,
|
||||
httpLink
|
||||
)
|
||||
|
||||
// 创建 apollo 客户端
|
||||
const apolloClient = new ApolloClient({
|
||||
link,
|
||||
cache: new InMemoryCache(),
|
||||
connectToDevTools: true,
|
||||
})
|
||||
```
|
||||
|
||||
### 插件设置
|
||||
|
||||
之前:
|
||||
|
||||
```js
|
||||
// 创建 apollo 客户端
|
||||
const apolloClient = new ApolloClient({
|
||||
networkInterface: createBatchingNetworkInterface({
|
||||
uri: 'http://localhost:3020/graphql',
|
||||
}),
|
||||
connectToDevTools: true,
|
||||
})
|
||||
|
||||
// 安装 vue 插件
|
||||
Vue.use(VueApollo, {
|
||||
apolloClient,
|
||||
})
|
||||
|
||||
new Vue({
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
之后:
|
||||
|
||||
```js
|
||||
const httpLink = new HttpLink({
|
||||
// 你需要在这里使用绝对路径
|
||||
uri: 'http://localhost:3020/graphql',
|
||||
})
|
||||
|
||||
// 创建 apollo 客户端
|
||||
const apolloClient = new ApolloClient({
|
||||
link: httpLink,
|
||||
cache: new InMemoryCache(),
|
||||
connectToDevTools: true,
|
||||
})
|
||||
|
||||
// 安装 vue 插件
|
||||
Vue.use(VueApollo)
|
||||
|
||||
// 创建一个 provider
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: apolloClient,
|
||||
})
|
||||
|
||||
// 使用 provider
|
||||
new Vue({
|
||||
provide: apolloProvider.provide(),
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
## 变更
|
||||
|
||||
查询 reducer 已经被移除。现在使用 `update` API 来更新缓存。
|
||||
|
||||
## 订阅
|
||||
|
||||
### 包
|
||||
|
||||
之前:
|
||||
|
||||
```
|
||||
npm install --save subscriptions-transport-ws
|
||||
```
|
||||
|
||||
之后:
|
||||
|
||||
```
|
||||
npm install --save apollo-link-ws apollo-utilities
|
||||
```
|
||||
|
||||
### 导入
|
||||
|
||||
之前:
|
||||
|
||||
```js
|
||||
import { SubscriptionClient, addGraphQLSubscriptions } from 'subscriptions-transport-ws'
|
||||
```
|
||||
|
||||
之后:
|
||||
|
||||
```js
|
||||
import { split } from 'apollo-link'
|
||||
import { WebSocketLink } from 'apollo-link-ws'
|
||||
import { getMainDefinition } from 'apollo-utilities'
|
||||
```
|
||||
|
||||
了解更多请查看 [apollo 官方文档](https://www.apollographql.com/docs/react/2.0-migration.html)。
|
||||
Reference in New Issue
Block a user