美文网首页vue
关于vue和apollo-client的结合(一)

关于vue和apollo-client的结合(一)

作者: rithe | 来源:发表于2018-07-27 18:10 被阅读361次

    基础版

    1、先来看看最基础的配置

    import {ApolloClient} from 'apollo-client'
    import {createHttpLink} from 'apollo-link-http'
    import {InMemoryCache} from 'apollo-cache-inmemory'
    import {ApolloLink} from 'apollo-link'
    import vue from 'vue'
    
    const httpLink = createHttpLink({
      uri: 'https://www.baidu.com/graphql'  //配置api调用连接
    })
    
    const middlewareLink = new ApolloLink((operation, forward) => {
      operation.setContext({
        headers: {
          'access-token': sessionStorage.getItem('access-token') || null
        }
      })  //request拦截器
    
      return forward(operation).map(response => {
        return response
      })  //response拦截器,但是此处并不能对错误响应进行拦截
    })
    
    const authLink = middlewareLink.concat(httpLink)
    
    const defaultOptions = {
      watchQuery: {
        fetchPolicy: 'network-only',
        errorPolicy: 'ignore'
      },
      query: {
        fetchPolicy: 'network-only',
        errorPolicy: 'all'
      }
    }
    
    const apollo = new ApolloClient({
      link: authLink,
      cache: new InMemoryCache(),
      connectToDevTools: true,
      defaultOptions: defaultOptions
    })
    
    export default apollo
    
    

    2、如果在请求需要带入cookie, 需要配置credentials参数

    const httpLink = createHttpLink({
      uri: 'https://www.baidu.com/graphql',
      credentials: 'include'
    })
    

    升级版

    1、加入错误响应拦截器

    npm install apollo-link-error --save
    
    const errorLink = onError(({networkError, response}) => {
      let errorMsg = ''
      if (!!response && response.errors !== undefined && response.errors.length) {
        errorMsg = !response.errors[0].message ? '服务器错误' : response.errors[0].message
      }
      if (!!networkError) {
        errorMsg = networkError.message
        if (networkError.result !== undefined) {
          errorMsg = networkError.result.success === false ? networkError.result.message : networkError.result.error
        }
      }
      if (!!errorMsg) {
        vue.prototype.$alert(errorMsg) //用vue的ale
      }
    })
    

    2、在前端apollo-client默认是不支持联合查询的。如果我们的graphql中存在如下的语法

    ...on A{
           name
     }
    ...on B{
          name
    }
    

    浏览器中就会报错

    You are using the simple (heuristic) fragment matcher, but your queries contain union or interface types.
    Apollo Client will not be able to able to accurately map fragments.To make this error go away, 
    use the IntrospectionFragmentMatcher as described in the docs: 
    https://www.apollographql.com/docs/react/recipes/fragment-matching.html
    

    解决方法如下,加入如下配置

    const fragmentMatcher = new IntrospectionFragmentMatcher({
      introspectionQueryResultData: {
        __schema: {
          types: [
            {
              kind: 'INTERFACE',
              name: 'Document',
              possibleTypes: [
                {name: 'MyInterface1'},
                {name: 'SomeInterface2'}
              ]
            }
          ]
        }
      }
    })
    

    最终版

    完整配置

    import {ApolloClient} from 'apollo-client'
    import {createHttpLink} from 'apollo-link-http'
    import {InMemoryCache, IntrospectionFragmentMatcher} from 'apollo-cache-inmemory'
    import {ApolloLink} from 'apollo-link'
    import {onError} from 'apollo-link-error'
    import vue from 'vue'
    
    const httpLink = createHttpLink({
      uri: 'https://www.baidu.com/graphql',
      credentials: 'include'
    })
    
    const middlewareLink = new ApolloLink((operation, forward) => {
      operation.setContext({
        headers: {
          'access-token': sessionStorage.getItem('access-token') || null
        }
      })
    
      return forward(operation).map(response => {
        return response
      })
    })
    
    const errorLink = onError(({networkError, response}) => {
      let errorMsg = ''
      if (!!response && response.errors !== undefined && response.errors.length) {
        errorMsg = !response.errors[0].message ? '服务器错误' : response.errors[0].message
      }
      if (!!networkError) {
        errorMsg = networkError.message
        if (networkError.result !== undefined) {
          errorMsg = networkError.result.success === false ? networkError.result.message : networkError.result.error
        }
      }
      if (!!errorMsg) {
        vue.prototype.$alert(errorMsg)
      }
    })
    
    const authLink = middlewareLink.concat(httpLink)
    
    const defaultOptions = {
      watchQuery: {
        fetchPolicy: 'network-only',
        errorPolicy: 'ignore'
      },
      query: {
        fetchPolicy: 'network-only',
        errorPolicy: 'all'
      }
    }
    
    const fragmentMatcher = new IntrospectionFragmentMatcher({
      introspectionQueryResultData: {
        __schema: {
          types: [
            {
              kind: 'INTERFACE',
              name: 'Document',
              possibleTypes: [
                {name: 'MyInterface1'},
                {name: 'SomeInterface2'}
              ]
            }
          ]
        }
      }
    })
    
    const apollo = new ApolloClient({
      link: errorLink.concat(authLink),
      cache: new InMemoryCache({fragmentMatcher}),
      connectToDevTools: true,
      defaultOptions: defaultOptions
    })
    
    export default apollo
    
    

    相关文章

      网友评论

        本文标题:关于vue和apollo-client的结合(一)

        本文链接:https://www.haomeiwen.com/subject/rwkgmftx.html