安装Apollo客户端插件
npm install vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag --save
安装加载器加载graphql后缀文件
打开根目录的vue.config.js
,在vueConfig
(不是Ant Design Pro框架的,是在webpack.base.config.js实现)下的chainWebpack
函数中加入以下内容:
// 支持.gql || .graphql文件
config.module
.rule("graphql")
.test(/\.(graphql|gql)$/)
.use("graphql-tag/loader")
.loader("graphql-tag/loader")
.end();
这样运行的时候能将文件后缀为.gql或.graphql的文件一起加入webpack打包
因为我是将graphql内容写成不同的文件来使用,类似使用axios有个单独的api文件夹一样,这样我们可以针对单独的业务存放一个单独的graphql文件,易读、也方便维护。
使用Vue集成graphql
在main.js
中添加以下内容:
/********************Graphql Apollo客户端******************/
import storage from 'store'
import {ApolloClient} from 'apollo-client'
import {HttpLink} from 'apollo-link-http'
import {InMemoryCache} from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
import {ApolloLink} from 'apollo-link'
const apiLink = new HttpLink({
uri: process.env.VUE_APP_API_GRAPHQL_URL //请求路径
})
const middlewareLink = new ApolloLink((operation, forward) => {
const token = storage.get('Access-Token')
operation.setContext({
headers: {
'api-token': token || null, // 如果不需要添加header头,这步可以忽略
}
})
return forward(operation)
})
const apiClient = new ApolloClient({
link: middlewareLink.concat(apiLink), // 如果不添加请求头直接放路径
cache: new InMemoryCache()
})
const apolloProvider = new VueApollo({
defaultClient: apiClient // 默认请求路径,如果只有一个请求就使用这个就行
})
Vue.use(VueApollo)
/********************Graphql客户端End******************/
这样就完成集成了。
如何使用
- 在
src
文件夹下创建文件夹graphql,专门存放graphql文件。 - 在
graphql
文件夹中创建一个user.gql(如果你使用VSCode编辑器,会提示你安装gql插件,安装上,开发方便很多),随便写一个查询语句试试水:
# 查询列表,q_shops是自定义的函数名,第3步引用时需要用到
query q_shops($page: Int!, $search: ShopSearch!) {
shops(first: 10, page: $page, search: $search) {
data {
id
user_id
name
phone
status
notice
address
location
created_at
}
paginatorInfo {
total
lastPage
currentPage
}
}
}
- 在Vue页面中使用
引入gql文件:
import { q_shops } from '@/graphql/shop.gql'
使用Apollo客户端执行gql语句
// 此处我是做一个列表查询,variables里的参数以及then里的业务实现根据自己需求编写
this.$apollo.query({
query: q_shops,
variables: {
"page": parameter.pageNo
},
})
.then((response) => {
console.log('graphql response', response)
var result = response.data.shops
result['current_page'] = result.paginatorInfo.currentPage
result['total'] = result.paginatorInfo.total
return result
})
.catch((error) => {})
这样就完成Apollo集成及使用了。
扩展
获取数据有缓存如何处理?
Apollo客户端默认有做数据缓存功能,当你第一次查询时会缓存当前查询语句的数据,第二次用相同的语句及参数查询不会进行网络请求,直接返回第一次查询的数据。从性能的角度来考虑,出发点挺好的,不过对于我们需要经常做增删改查的功能时,就不实用了。解决方式很简单,在query时加入fetchPolicy: 'no-cache'
即可。以上述的查询语句为例,实现代码如下:
this.$apollo.query({
query: q_shops,
variables: {
"page": parameter.pageNo
},
fetchPolicy: 'no-cache' // 加上这句即可
})
.then((response) => {
console.log('graphql response', response)
var result = response.data.shops
result['current_page'] = result.paginatorInfo.currentPage
result['total'] = result.paginatorInfo.total
return result
})
.catch((error) => {})
做简易的封装
每次执行graphql语句要写一大堆结构代码,太麻烦了。把相同结构代码封装起来(个人方式封装,不一定适用大家,能用的拿去就好),具体实现:
- 在
/src/utils/
文件夹中创建apollo.js
(不喜欢这个名字随便换)。 - 封装代码如下:
/**
* 自封装的graphql Apollo工具类
*/
/**
* 查询单条信息
* @param {*} _this 传this
* @param {*} graphqlStr 对应的graphql查询语句
* @param {*} params 参数
* @param {*} schema 返回数据有一层schema,需要拿到这一层的数据
* @param {*} callback 回调函数
*/
export function querySingle(_this, graphqlStr, params, schema, callback = null) {
return _this.$apollo.query({
query: graphqlStr,
variables: params,
fetchPolicy: 'no-cache'
})
.then((response) => {
console.log('graphql response', response)
var result = schema ? response.data[schema] : response.data
callback && callback(result, true)
return result
})
.catch((error) => {
_this.$notification['error']({
message: '查询失败',
description: '错误信息:' + error.message,
})
})
}
/**
* 查询列表
* @param {*} _this 传this
* @param {*} graphqlStr 对应的graphql查询语句
* @param {*} pageParams 分页参数
* @param {*} schema 返回数据有一层schema,需要拿到这一层的数据,再组装分页数据给STable
* @param {*} callback 回调函数
*/
export function queryList(_this, graphqlStr, pageParams, schema, callback = null) {
var params = {}
if (pageParams.pageNo) {
params = {
"page": pageParams.pageNo
}
} else {
params = pageParams
}
console.log(pageParams, graphqlStr)
return _this.$apollo.query({
query: graphqlStr,
variables: params,
fetchPolicy: 'no-cache'
})
.then((response) => {
console.log('graphql response', response)
var result = response.data[schema]
result['current_page'] = result.paginatorInfo.currentPage
result['total'] = result.paginatorInfo.total
if (callback) {
return callback(result, true)
}
return result
})
.catch((error) => {
_this.$notification['error']({
message: '查询失败',
description: '错误信息:' + error.message,
})
})
}
/**
* 多个查询集合
* @param {*} _this 传this
* @param {*} graphqlStr 对应的graphql查询语句
* @param {*} params 参数
* @param {*} callback 回调函数
*/
export function queryMulti(_this, graphqlStr, params, callback = null) {
console.log(params, graphqlStr)
return _this.$apollo.query({
query: graphqlStr,
variables: params,
fetchPolicy: 'no-cache'
})
.then((response) => {
console.log('graphql response', response)
var result = response.data
if (callback) {
callback(result, true)
}
return result
})
.catch((error) => {
_this.$notification['error']({
message: '查询失败',
description: '错误信息:' + error.message,
})
})
}
/**
* 创建数据
* @param {*} _this 传this
* @param {*} graphqlStr 对应的graphql查询语句
* @param {*} params 参数
* @param {*} callback 回调函数
*/
export function createData(_this, graphqlStr, params, callback = null) {
return _this.$apollo.mutate({
mutation: graphqlStr,
variables: params
})
.then((response) => {
console.log('graphql response', response)
callback && callback(response, true)
return response
})
.catch((error) => {
if (error.graphQLErrors[0].extensions.validation) {
var validation = error.graphQLErrors[0].extensions.validation
var msg = (validation[Object.keys(validation)[0]])[0]
_this.$notification['error']({
message: '新建失败',
description: '错误信息:' + msg,
})
} else {
_this.$notification['error']({
message: '新建失败',
description: '错误信息:' + error.graphQLErrors[0].message,
})
}
})
}
/**
* 修改数据
* @param {*} _this 传this
* @param {*} graphqlStr 对应的graphql查询语句
* @param {*} params 参数
* @param {*} callback 回调函数
*/
export function updateData(_this, graphqlStr, params, callback = null) {
return _this.$apollo.mutate({
mutation: graphqlStr,
variables: params,
})
.then((response) => {
console.log('graphql response', response)
callback && callback(response, true)
return response
})
.catch((error) => {
if (error.graphQLErrors[0].extensions.validation) {
var validation = error.graphQLErrors[0].extensions.validation
var msg = (validation[Object.keys(validation)[0]])[0]
_this.$notification['error']({
message: '修改失败',
description: '错误信息:' + msg,
})
} else {
_this.$notification['error']({
message: '修改失败',
description: '错误信息:' + error.graphQLErrors[0].message,
})
}
})
}
/**
* 删除数据
* @param {*} _this 传this
* @param {*} graphqlStr 对应的graphql查询语句
* @param {*} params 参数
* @param {*} callback 回调函数
*/
export function deleteData(_this, graphqlStr, params, callback = null) {
return _this.$apollo.mutate({
mutation: graphqlStr,
variables: params,
})
.then((response) => {
console.log('graphql response', response)
callback && callback(response, true)
return response
})
.catch((error) => {
if (error.graphQLErrors[0].extensions.validation) {
var validation = error.graphQLErrors[0].extensions.validation
var msg = (validation[Object.keys(validation)[0]])[0]
_this.$notification['error']({
message: '删除失败',
description: '错误信息:' + msg,
})
} else {
_this.$notification['error']({
message: '删除失败',
description: '错误信息:' + error.graphQLErrors[0].message,
})
}
})
}
以上对增删改查都做了简单的封装,以及多个graphql语句执行的函数封装,错误提示等处理。
- 封装后的使用:
// 引入封装的文件
import { querySingle, queryList, createData, updateData } from '@/utils/apollo'
...
// 使用封装后的查询,传参调用就完事了
var vars = {}
vars['search'] = {}
vars['page'] = parameter.pageNo
return queryList(this, q_shops, vars, 'shops')
参考并感谢
https://segmentfault.com/a/1190000016320117
https://segmentfault.com/q/1010000016610922
https://blog.csdn.net/winnie__wei/article/details/80598309
https://blog.csdn.net/Missbelover/article/details/102651403
https://www.cnblogs.com/lhxsoft/p/11904388.html