安裝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實(shí)現(xiàn))下的chainWebpack函數(shù)中加入以下內(nèi)容:
// 支持.gql || .graphql文件
config.module
.rule("graphql")
.test(/\.(graphql|gql)$/)
.use("graphql-tag/loader")
.loader("graphql-tag/loader")
.end();
這樣運(yùn)行的時(shí)候能將文件后綴為.gql或.graphql的文件一起加入webpack打包
因?yàn)槲沂菍raphql內(nèi)容寫成不同的文件來(lái)使用,類似使用axios有個(gè)單獨(dú)的api文件夾一樣,這樣我們可以針對(duì)單獨(dú)的業(yè)務(wù)存放一個(gè)單獨(dú)的graphql文件,易讀、也方便維護(hù)。
使用Vue集成graphql
在main.js中添加以下內(nèi)容:
/********************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 //請(qǐng)求路徑
})
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), // 如果不添加請(qǐng)求頭直接放路徑
cache: new InMemoryCache()
})
const apolloProvider = new VueApollo({
defaultClient: apiClient // 默認(rèn)請(qǐng)求路徑,如果只有一個(gè)請(qǐng)求就使用這個(gè)就行
})
Vue.use(VueApollo)
/********************Graphql客戶端End******************/
這樣就完成集成了。
如何使用
- 在
src文件夾下創(chuàng)建文件夾graphql,專門存放graphql文件。 - 在
graphql文件夾中創(chuàng)建一個(gè)user.gql(如果你使用VSCode編輯器,會(huì)提示你安裝gql插件,安裝上,開發(fā)方便很多),隨便寫一個(gè)查詢語(yǔ)句試試水:
# 查詢列表,q_shops是自定義的函數(shù)名,第3步引用時(shí)需要用到
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頁(yè)面中使用
引入gql文件:
import { q_shops } from '@/graphql/shop.gql'
使用Apollo客戶端執(zhí)行g(shù)ql語(yǔ)句
// 此處我是做一個(gè)列表查詢,variables里的參數(shù)以及then里的業(yè)務(wù)實(shí)現(xiàn)根據(jù)自己需求編寫
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集成及使用了。
擴(kuò)展
獲取數(shù)據(jù)有緩存如何處理?
Apollo客戶端默認(rèn)有做數(shù)據(jù)緩存功能,當(dāng)你第一次查詢時(shí)會(huì)緩存當(dāng)前查詢語(yǔ)句的數(shù)據(jù),第二次用相同的語(yǔ)句及參數(shù)查詢不會(huì)進(jìn)行網(wǎng)絡(luò)請(qǐng)求,直接返回第一次查詢的數(shù)據(jù)。從性能的角度來(lái)考慮,出發(fā)點(diǎn)挺好的,不過(guò)對(duì)于我們需要經(jīng)常做增刪改查的功能時(shí),就不實(shí)用了。解決方式很簡(jiǎn)單,在query時(shí)加入fetchPolicy: 'no-cache'即可。以上述的查詢語(yǔ)句為例,實(shí)現(xiàn)代碼如下:
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) => {})
做簡(jiǎn)易的封裝
每次執(zhí)行g(shù)raphql語(yǔ)句要寫一大堆結(jié)構(gòu)代碼,太麻煩了。把相同結(jié)構(gòu)代碼封裝起來(lái)(個(gè)人方式封裝,不一定適用大家,能用的拿去就好),具體實(shí)現(xiàn):
- 在
/src/utils/文件夾中創(chuàng)建apollo.js(不喜歡這個(gè)名字隨便換)。 - 封裝代碼如下:
/**
* 自封裝的graphql Apollo工具類
*/
/**
* 查詢單條信息
* @param {*} _this 傳this
* @param {*} graphqlStr 對(duì)應(yīng)的graphql查詢語(yǔ)句
* @param {*} params 參數(shù)
* @param {*} schema 返回?cái)?shù)據(jù)有一層schema,需要拿到這一層的數(shù)據(jù)
* @param {*} callback 回調(diào)函數(shù)
*/
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: '錯(cuò)誤信息:' + error.message,
})
})
}
/**
* 查詢列表
* @param {*} _this 傳this
* @param {*} graphqlStr 對(duì)應(yīng)的graphql查詢語(yǔ)句
* @param {*} pageParams 分頁(yè)參數(shù)
* @param {*} schema 返回?cái)?shù)據(jù)有一層schema,需要拿到這一層的數(shù)據(jù),再組裝分頁(yè)數(shù)據(jù)給STable
* @param {*} callback 回調(diào)函數(shù)
*/
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: '錯(cuò)誤信息:' + error.message,
})
})
}
/**
* 多個(gè)查詢集合
* @param {*} _this 傳this
* @param {*} graphqlStr 對(duì)應(yīng)的graphql查詢語(yǔ)句
* @param {*} params 參數(shù)
* @param {*} callback 回調(diào)函數(shù)
*/
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: '錯(cuò)誤信息:' + error.message,
})
})
}
/**
* 創(chuàng)建數(shù)據(jù)
* @param {*} _this 傳this
* @param {*} graphqlStr 對(duì)應(yīng)的graphql查詢語(yǔ)句
* @param {*} params 參數(shù)
* @param {*} callback 回調(diào)函數(shù)
*/
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: '錯(cuò)誤信息:' + msg,
})
} else {
_this.$notification['error']({
message: '新建失敗',
description: '錯(cuò)誤信息:' + error.graphQLErrors[0].message,
})
}
})
}
/**
* 修改數(shù)據(jù)
* @param {*} _this 傳this
* @param {*} graphqlStr 對(duì)應(yīng)的graphql查詢語(yǔ)句
* @param {*} params 參數(shù)
* @param {*} callback 回調(diào)函數(shù)
*/
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: '錯(cuò)誤信息:' + msg,
})
} else {
_this.$notification['error']({
message: '修改失敗',
description: '錯(cuò)誤信息:' + error.graphQLErrors[0].message,
})
}
})
}
/**
* 刪除數(shù)據(jù)
* @param {*} _this 傳this
* @param {*} graphqlStr 對(duì)應(yīng)的graphql查詢語(yǔ)句
* @param {*} params 參數(shù)
* @param {*} callback 回調(diào)函數(shù)
*/
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: '錯(cuò)誤信息:' + msg,
})
} else {
_this.$notification['error']({
message: '刪除失敗',
description: '錯(cuò)誤信息:' + error.graphQLErrors[0].message,
})
}
})
}
以上對(duì)增刪改查都做了簡(jiǎn)單的封裝,以及多個(gè)graphql語(yǔ)句執(zhí)行的函數(shù)封裝,錯(cuò)誤提示等處理。
- 封裝后的使用:
// 引入封裝的文件
import { querySingle, queryList, createData, updateData } from '@/utils/apollo'
...
// 使用封裝后的查詢,傳參調(diào)用就完事了
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