# 智能查询

在组件的 apollo 定义中声明的每个查询(不以 $ 字符开头)都会创建一个智能查询对象。

# 选项

  • query:GraphQL 文档(可以是一个文件或一个 gql 字符串)。
  • variables:对象或返回对象的响应式函数。每个键将用 '$' 映射到 GraphQL 文档中,例如 foo 将变为 $foo。
  • throttle:变量更新节流时间(毫秒)。
  • debounce:变量更新防抖时间(毫秒)。
  • pollInterval:使用轮询自动更新的时间(表示每隔 x 毫秒重新获取一次)。
  • update(data) {return ...} 用来自定义设置到 vue 属性中的值,例如当字段名称不匹配时。
  • result(ApolloQueryResult, key) 是收到结果时调用的钩子(更多参见 ApolloQueryResult (opens new window) 的文档)。key 是在 apollo 选项中定义此查询时使用的键名。
  • error(error, vm, key, type, options) 是出现错误时调用的钩子。error 是一个具有 graphQLErrors 属性或 networkError 属性的 Apollo 错误对象。vm 是关联组件的实例。key 是智能查询的键名。type 是 'query' 或 'subscription' 中的一项。options 是最终的 watchQuery 选项对象。
  • loadingKey 将更新你传递的值所对应的组件数据属性。你应该在组件的 data() 钩子中将此属性初始化为 0 。当查询正在加载时,此属性将增加 1;当不再加载时,它将减去 1。这样,该属性可以表示当前正在加载中的查询的计数器。
  • watchLoading(isLoading, countModifier) 是一个在查询的加载状态发生变化时调用的钩子。countModifier 参数当查询正在加载时等于 1,不再加载时为 -1。
  • manual 是一个禁用自动属性更新的布尔值。如果使用它,你需要指定一个 result 回调函数(参见下面的示例)。
  • deep 是一个在 Vue 侦听器上使用 deep: true 的布尔值。
  • skip 是一个布尔值或一个返回布尔值的(响应式)函数。该函数的参数一个是当前组件,另一个是智能查询的键名,因此可以在 $query 或是 ApolloProvider 的 defaultOptions 中使用。
  • subscribeToMore:一个或一组 subscribeToMore 选项 对象。
  • prefetch 是一个布尔值或函数来确定是否应该预取查询。详见 服务端渲染。
  • 你还可以使用任意 watchQuery 的选项(参见 Apollo 文档 (opens new window))。

示例:

// Apollo 具体选项
apollo: {
  // 带参数的高级查询
  // vue 会侦听 'variables' 方法
  pingMessage: {
    query: gql`query PingMessage($message: String!) {
      ping(message: $message)
    }`,
    // 响应式参数
    variables () {
      // 在这里使用 vue 的响应式属性
      return {
        message: this.pingInput,
      }
    },
    // 轮询间隔,以毫秒为单位
    pollInterval: 10000,
    // 也可以通过 vue 响应式属性设置轮询间隔
    pollInterval() {
      return this.pollInterval;
    },
    // 变量:深度对象侦听
    deep: false,
    // 我们使用自定义的 update 回调函数,因为字段名称不匹配
    // 默认情况下,将使用 '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 也可以这样写:

update: data => data.ping

手动模式示例:

{
  query: gql`...`,
  manual: true,
  result ({ data, loading }) {
    if (!loading) {
      this.items = data.items
    }
  },
}

# 属性

# skip

你可以使用 skip 来暂停或停止暂停:

this.$apollo.queries.users.skip = true

# loading

查询是否正在加载中:

this.$apollo.queries.users.loading

# 方法

# refresh

停止并重新启动查询:

this.$apollo.queries.users.refresh()

# start

开始查询:

this.$apollo.queries.users.start()

# stop

停止查询:

this.$apollo.queries.users.stop()

# fetchMore

为分页加载更多数据:

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 订阅来订阅更多数据:

// 我们需要在重新订阅之前取消订阅
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

重新获取查询,可选择使用新变量:

this.$apollo.queries.users.refetch()
// 使用新变量
this.$apollo.queries.users.refetch({
  friendsOf: 'id-user'
})

# setVariables

更新查询中的变量,如果发生了改变则重新获取查询。要强制重新获取,请使用 refetch。

this.$apollo.queries.users.setVariables({
  friendsOf: 'id-user'
})

# setOptions

更新 Apollo watchQuery (opens new window) 选项并重新获取:

this.$apollo.queries.users.setOptions({
  fetchPolicy: 'cache-and-network'
})

# startPolling

使用轮询启动自动更新(这意味着每隔 x ms 进行重新获取):

this.$apollo.queries.users.startPolling(2000) // ms

# stopPolling

停止轮询:

this.$apollo.queries.users.stopPolling()
上次更新时间: 11/3/2020, 10:45:03 AM