在上篇 基于 NestJS 快速搭建 GraphQL 服务中,我们使用 NestJS 快速搭建了一个具有 CRUD 功能的 GraphQL API 服务。所以这篇文章将简单示例在 Vue 项目中,如何像使用 axios 那样便捷的调用 GraphQL API 实现增删改查;
技术栈 Vue + TypeScript + Vue-Apollo
第一步,创建项目
-
使用@vue/cli 创建项目
# 创建项目 vue create vue-apollo-graphql输入命令后命令行询问会询问是否使用预设:
Vue CLI v4.4.6 ? Please pick a preset: default (babel, eslint) > Manually select features # 选择手动配置,回车然后会让我们选择特性(上下箭头移动选项,空格切换选中):
Vue CLI v4.4.6 ? Please pick a preset: Manually select features ? Check the features needed for your project: >(*) Babel (*) TypeScript # 使用ts ( ) Progressive Web App (PWA) Support (*) Router ( ) Vuex ( ) CSS Pre-processors (*) Linter / Formatter ( ) Unit Testing ( ) E2E Testing后面还会询问是否使用 class 风格的 vue 组件等等,个人比较喜欢 class 风格,所以选择 Yes,完整选项如下:
-
添加 vue-cli-plugin-apollo 插件
vue add apollo添加完成后插件会询问我们是否添加示例代码,是否添加 GraphQL 服务,是否配置 Apollo 引擎,我们这里不太需要这些,直接一路选 N 就可以了:
-
启动项目
yarn yarn serve
第二步,配置 Apollo-GraphQL
-
修改根目录下的
apollo.config.js用于配置 VScode 的Apollo GraphQL插件,获取服务器 的 GraphQL 类型定义;需要 VScode 提前安装
Apollo GraphQL插件module.exports = { client: { service: { name: env.VUE_APP_APOLLO_ENGINE_SERVICE, url: env.APOLLO_ENGINE_API_ENDPOINT, // GraphQL服务url skipSSLValidation: true, addTypename: false, // localSchemaFile: './src/graphql/schema.graphql', //本地类型定义 }, includes: ['src/**/*.{js,jsx,ts,tsx,vue,gql}'], }, engine: { endpoint: env.APOLLO_ENGINE_API_ENDPOINT, apiKey: env.VUE_APP_APOLLO_ENGINE_KEY, }, }配置详情可以查看
apollo-graphql的官网 配置文档; -
修改
src/vue-apollo.ts用于设置 vue-apollo 连接配置;//省略了其他未变动设置 const defaultOptions = { // 设置去除__typename字段 inMemoryCacheOptions: { addTypename: false, }, }默认下 apollo-graphql 返回的数据里会有一个
__typename字段,用于确定返回类型。但是我们并不需要,而且会影响表单的使用,所以这里设置不添 加__typename字段
第三步,使用 Apollo-GraphQL 进行 CRUD
首先我们在 src/components 下新建ApolloExample.vue;
-
新增商品
1.1. 在
src/graphql下创建addOneGoods.gql,用于新增商品:mutation addOneGoods($goods: GoodsInsertTypeGraphql!) { addOneGoods(goods: $goods) { id name price count remark } }.gql的语法可以查看官网 GraphQL 学习文档1.2. 引入
addOneGoods.gql,使用this.$apollo.mutate调用此 Mutations,新增商品信息:import ADD_ONE_GOODS from '@/graphql/addOneGoods.gql' // 新增一个商品 handleAddOneGoods(goods: IGoods) { this.$apollo .mutate({ mutation: ADD_ONE_GOODS, variables: { goods: goods }, }) .then(() => { this.$message.success('新增商品成功') }) .catch(e => { this.$notify.error(`请求错误: ${e.message}`) }) }IGoods是商品的类型定义:export interface IGoods { id?: string name: string price: number count: number remark: string }
-
查询商品列表
2.1. 在
src/graphql下创建getAllGoods.gql,用于查询所有商品;query getAllGoods { getAllGoods { id name price count remark } }2.2. 在
components/ApolloExample.vue里引入getAllGoods.gql,使用this.$apollo.query调用此 Query;import GET_ALL_GOODS from '@/graphql/getAllGoods.gql' getAllGoodsData() { this.$apollo .query({ query: GOODS }) .then(res => { this.goodsList = res.data.getAllGoods }) .catch(e => { this.$notify.error(`获取商品列表失败: ${e.message}`) this.goodsList = [] }) } -
更新商品信息
3.1. 在
src/graphql下创建updateGoods.gql,用于更新商品;mutation updateGoods($goods: GoodsInputTypeGraphql!) { updateGoods(goods: $goods) { id name price count remark } }3.2. 引入
updateGoods.gql,使用this.$apollo.mutate调用此 Mutations,更新商品信息;import UPDATE_GOODS from '@/graphql/updateGoods.gql' // 更新商品信息 handleUpdateGoods(goods: IGoods) { this.$apollo .mutate({ mutation: UPDATE_GOODS, variables: { goods: goods }, }) .then(() => { this.$message.success('修改商品信息成功') }) .catch(e => { this.$notify.error(`请求错误: ${e.message}`) }) }
-
删除商品
4.1. 在
src/graphql下创建deleteOneGoods.gql,用于删除商品;mutation deleteOneGoods($id: String!) { deleteOneGoods(id: $id) }4.2. 引入
deleteOneGoods.gql,使用this.$apollo.mutate调用此 Mutations,更新商品信息;import DELETE_ONE_GOODS from '@/graphql/deleteOneGoods.gql' // 删除一个商品 handleDelete(goods: IGoods) { this.$apollo .mutate({ mutation: DELETE_ONE_GOODS, variables: { id: goods.id }, }) .then(() => { this.$message.success('删除商品成功') }) .catch(e => { this.$notify.error(`请求错误: ${e.message}`) }) }
这样我们就完成基础的 CRUD 操作了,最后为了方便展示,简单用 element-ui 写一下界面:
总结一下:
大致使用流程和 axios 请求差别不大
- 定义
.gql文件类似于 axios 定义 api 请求; - 引入
.gql文件类似于引入定义 api 请求方法; - 使用
this.$apollo.query或者mutate,类似于axios.get或者axios.post调用接口,传递参数;
踩坑:
由于 vue-apollo 库默认使用了接口缓存,所以短时间内重复的 query 请求不会去获取最新数据,所以在实际使用this.$apollo.mutate方法的时候都会写update回调
,用于更新对应 query 的缓存数据,完整代码中有示例;