首先需要提前了解一下
Vue apollo
Graphql
为了webpack 能够解析Graphql 文件,需要在vue.config.js文件中配置
chainWebpack: config => {
config.module
.use("vue-loader")
.loader("vue-loader")
.end()
}
安装需要的依赖
npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag apollo-link-error vue-cli-plugin-apollo
在项目根目录下创建apollo文件夹,创建 apollo-options.js(apollo 相关配置) 和 vue-apollo.js(配置Vue apollo)文件
//apollo-options.js
import { ApolloLink } from "apollo-link";
import { createHttpLink } from "apollo-link-http";
import { onError } from "apollo-link-error";
import { InMemoryCache } from "apollo-cache-inmemory";
import ApolloClient from "apollo-client";
import { Message } from "element-ui";
import router from "@root/router";
import i18nInstance from "@root/i18n";
const httpLink = createHttpLink({
uri:
process.env.NODE_ENV === "development"
? '本地的开发路径'
: process.env.apiUrl, // 项目通过webpack配的api调用连接
// 如果需要设置代理
// '/graphql': {
// target: "需要代理的路径",
// changeOrigin: true,
// pathRewrite: {
// '^/graphql': '/graphql'
// }
// },
fetch(uri, options) {
const { operationName } = JSON.parse(options.body as string);
// 由于 graphql 请求路径在浏览器中统一为‘/graphql’, 为了方便查看拼接上接口名称
return fetch(`${uri}/?opname=${operationName}`, options);
}
});
// 中间件为每个请求带上必要请求头参数
const middlewareLink = new ApolloLink((operation, forward) => {
operation.setContext({
headers: {
"AUTH-TOKEN": localStorage.getItem("AuthToken"),
Language: i18nInstance.locale
}
});
return forward(operation).map(response => {
// 过滤apollo 自带的__typename
let filterData = JSON.stringify(response).replace(
/\,"__typename\"[:]\"[0-9a-zA-Z_|!|(|)]{1,}\"/g,
""
);
return JSON.parse(filterData);
})
});
const onRequestError = () => {
// 配置项目请求是否过期
let hasBeenExpire = false;
return (errorData) => {
const { networkError, response } = errorData
if (networkError) {
Message.error("networkError");
return
}
const error: any = response && response.errors && response.errors[0]
let { code = "", message = 'Error' } = error || {}
// 如果已经过期那就不再弹出错误信息 也不会多次触发路由跳转
if (hasBeenExpire) {
return
}
// 如果过期 页面跳转
if (code === "0002"){
hasBeenExpire = true
router.push({ name: "Logout"})
}
Message.error(message);
}
}
// 统一拦截请求错误
const errorLink = onError(error => onRequestError(error));
const options: any = {
cache: new InMemoryCache(),
link: errorLink.concat(middlewareLink.concat(httpLink)),
defaultOptions: {
watchQuery: {
fetchPolicy: "no-cache"
},
query: {
fetchPolicy: "no-cache"
}
}
};
export const gqlClient = new ApolloClient(options);
export default options;
// vue-apollo.js
import Vue from "vue";
import VueApollo from "vue-apollo";
import {
createApolloClient,
restartWebsockets
} from "vue-cli-plugin-apollo/graphql-client";
// Install the vue plugin
Vue.use(VueApollo);
export function createProvider() {
// Create vue apollo provider
const apolloProvider = new VueApollo({
defaultClient: apolloClient,
defaultOptions: {
$query: {
fetchPolicy: "no-cache"
}
},
});
return apolloProvider。provide();
}
由于是Vue结合Vuex,请求都会在 VueX的action中进行,所以将Graphql的请求注入到了rootState中,具体rootState 可到Vuex官网此处了解。
export default new Vuex.Store({
// 可以Vuex的rootState中注入gqlClient
state: {
gql: gqlClient
},
modules: {},
mutations: {},
actions: {}
});
//main.js
import {createProvider} from @/apollo/vue-apollo.js;
//...
const apolloProvider = createProvider();
new Vue({
router,
store,
i18n: i18n,
provide: apolloProvider,
}).$mount("#app");
至此配置完成,那么如何使用呢
在根目录下创建 graphql 文件,在此文件下创建各个模块的graphql文件,也就是前端写查询Schemal 的地方。如以下:
// graphql/user.gql
query getUser($input: updateUser){
api:getUser(input:$input){
edges{
node{
userCode
userName
}
}
}
}
mutation updateUser ($input: updateUser!) {
api: updateUser(updateUser: $input){
success
}
}
mutation createUser($input: [createUser]!){
api: createUser(createUser: $input){
success
list{
updateUser
createUser
}
}
}
mutation deleteUser($input: deleteUser!){
api: deleteUser(deleteUser: $input){
success
}
}
由于此前已经将Graphql请求注入到Vuex 中,所以只需要在action中请求数据即可
import {
getUser,
updateUser,
createUser,
deleteUser
} from "@/graphql/user.gql";
export default {
namespaced: true,
state: {
userList: [],
},
getters: {
},
actions: {
// 订单列表
async getUser({ commit, rootState }, data) {
const res = await rootState.gql.query({
query: getUser,
variables: {
input:data
}
});
commit("setUserList",res.data.api.edges)
return res;
},
// 订单列表
async updateUser({ commit, rootState }, data) {
const {
data: { api }
} = await rootState.gql.mutate({
mutation: updateUser,
variables: {
updateUser: data
}
});
return api;
},
},
mutations: {
setUserList(state, data) {
state.userList = data;
}
}
};
在页面中直接使用Vuex 中action方法即可
<script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
import { State, Getter, Action, Mutation, namespace } from "vuex-class";
const user = namespace("user");
@Component({
components: {},
})
export default class OMSIndex extends Vue {
@user.State userList;
@user.Action getUser;
async mounted() {
await this.getData();
}
async getData() {
let sendParams = xxx;
let res = await this.getUser(sendParams);
console.log(res);//获取到数据了
}
}
</script>