Vue <3 GraphQL
TL;DR:我做了这个:https://vuex-orm.github.io/vuex-orm-graphql/
这是我在 dev.to 上发表的第一篇文章,我想用它与这个令人惊叹的社区分享我当前的开源项目 :)
Vuex-ORM 的 GraphQL 插件和本文由德国i22 Digitalagentur GmbH提供支持。
旅程的开始
在我目前的业余项目中,我使用了 JSON/REST API,并通过 JSData 连接了前端单页应用程序。这种设置让我很不满意,还带来了很多问题。
然后我发现了Vuex-ORM,它提供了我在 Vue 中处理模型所需的一切,并且具有真正的响应式,速度极快,并且使用了 Vuex。我感觉应该用 Vuex-ORM 替换 JSData。但是:它没有插件可以连接 API。我不想在组件中写太多样板代码,也不喜欢在与 API 通信的细节上费劲。将单页应用程序与 API 集成可能会很麻烦。但其实不应该如此。
今年早些时候,我在新的全职工作中学习了 GraphQL。它真的太棒了。试用了一段时间后,我表示非常喜欢它,觉得我可以用 GraphQL 替换我业余项目中的 REST/JSON API。
后来,我在i22的全职工作中启动了一个项目,项目设置和我的业余项目非常相似,所以我决定尝试一下 Vuex-ORM。但我们承诺会使用 GraphQL(就像我们所有其他项目一样)。Vuex-ORM 没有 JSON/REST 插件,也没有 GraphQL 插件。我想,我可以写一个。我想,应该不难:我们已经有了模型定义和 GraphQL API,我只需将模型定义转换为 GraphQL 查询即可。我可以使用 apollo-client 库。这个插件应该能让与 API 的通信变得非常顺畅。无需样板代码,也无需摆弄 JSON 结构之类的。那就开始吧!
这比我想象的要困难得多,但经过几周的开发,我得到了一个基本可以工作的插件,它有一个最小的组件样板,只需要响应性和所有那些花哨的东西就可以了。
是时候进行下一步了:将我的副项目从 JSON/REST + JSData 迁移到 Vuex-ORM + GraphQL。在此期间,我发现了插件中的一些错误并修复了它们,编写了一些测试并添加了一些缺失的功能。
如今,经过几个月的微调、测试,以及Vuex-ORM 维护者Kia的大力帮助,我终于开发出了一个运行良好的 Vuex-ORM GraphQL 插件,它包含所有基本功能、文档,并且我目前正在使用的两个项目都在使用它。它运行得非常好。我现在对它非常满意 :)
现在是时候与社区分享我的成果了。在本文的剩余部分,我将向您展示 Vuex-ORM-GraphQL 插件的工作原理以及如何在您的项目中使用它。请记住:这只是一个基本示例。更多详细信息,请参阅Vuex-ORM和Vuex-ORM-GraphQL的文档。祝您使用愉快!
工作原理
我假设您有使用 Vue 和 GraphQL 的经验。
Vuex-ORM
首先我们必须设置 Vuex-ORM,这非常简单。
yarn add @vuex-orm/core
然后在您的应用程序的某处创建一个store.js
目录models
。
假设我们正在构建一个简单的博客。有posts
和comments
。所以我们需要两个模型。让我们在新models
目录中创建它们:
models/post.js
:
import { Model } from '@vuex-orm/core';
import Comment from './comment';
/**
* The Vuex-ORM post model
*/
export default class Post extends Model {
// Tell Vuex-ORM the path where the records should be stored in Vuex
static entity = 'posts';
// Tell Vuex-ORM-GraphQL to eagerly load all comments when we fetch a post.
static eagerLoad = ['comments'];
// Setup the fields and relations for Vuex-ORM
static fields () {
return {
id: this.increment(),
title: this.string(''),
content: this.string(''),
publishedAt: this.string(''),
comments: this.hasMany(Comment, 'postId')
}
}
}
models/comment.js
:
import { Model } from '@vuex-orm/core';
import Post from './post';
/**
* The Vuex-ORM comment model
*/
export default class Comment extends Model {
// Tell Vuex-ORM the path where the records should be stored in Vuex
static entity = 'comment';
// Setup the fields for Vuex-ORM
static fields () {
return {
id: this.increment(),
author: this.string(''),
content: this.string(''),
publishedAt: this.string(''),
postId: this.number(0),
post: this.belongsTo(Post, 'postId')
}
}
}
如你所见,为 Vuex-ORM 设置模型非常简单。现在我们需要像这样设置 Vuex store:
store.js
import Vue from 'vue';
import Vuex from 'vuex';
import VuexORM from '@vuex-orm/core';
import Post from './models/post';
import Comment from './models/comment';
// Setup Vuex
Vue.use(Vuex);
// Setup Vuex-ORM database
const database = new VuexORM.Database();
database.register(Post, {});
database.register(Comment, {});
// Create Vuex Store and register the Vuex ORM plugin.
export default new Vuex.Store({
plugins: [VuexORM.install(database)]
});
之后,我们就可以在组件中创建新记录、查找、更改和删除它们了:
import Post from 'store/models/post';
Post.create({
title: 'Example Blog Post',
content: 'Lorem ipsum dolor sit amet',
publishedAt: (new Date()).toISOString()
});
const allPosts = Post.all();
Vuex-ORM GraphQL 插件
下一步,我们将为 Vuex-ORM 设置我的新 GraphQL 插件,这非常简单,因为该插件隐藏了 apollo-http-link、apollo-client 等所有复杂的功能。它设计为安装后即可使用:
yarn add @vuex-orm/plugin-graphql
像这样改变store.js
:
// ...
database.register(Post, {});
database.register(Comment, {});
// --8<-------------
// This is the new part
import installVuexORMGraphQL from '@vuex-orm/plugin-graphql';
VuexORM.use(installVuexORMGraphQL, {
database: database,
debug: process.env.NODE_ENV !== 'production'
});
// --8<-------------
// Create Vuex Store and register the Vuex ORM plugin.
export default new Vuex.Store({
plugins: [VuexORM.install(database)]
});
这里没什么特别的,我们只需将 Vuex-ORM-GraphQL 插件注册为 Vuex-ORM 插件并传递数据库即可。无需执行其他操作。正如我所说:设置非常简单 ;)
存储与持久化操作
在使用带有 GraphQL 插件的 Vuex-ORM 时,您必须区分两种类型的 Vuex 操作:
- 存储操作:从 Vuex Store 检索数据或将数据保存到 Vuex Store(
Vue Component <--> Vuex Store
) - 持久化操作:从 GraphQL API 加载数据或将数据持久化到 GraphQL API(
Vuex Store <--> GraphQL Server
)
下表列出了所有操作及其作用:
增删改查 | 仅限 Vuex | 持久化到 GraphQL API |
---|---|---|
读 | find() ,,all() query() |
fetch() |
创造 | create() 或者insert() |
$persist() |
更新 | $update() |
$push() |
删除 | $delete() |
$destroy() |
例子
设置完成后,我们可以使用 Vuex-ORM 从 GraphQL API 获取数据并以响应式方式显示它:
<template>
<div class="blog">
<article v-for="post in posts" :key="post.id" class="blog__post">
<h2>{{post.title}}</h2>
<small>{{post.publishedAt}}</small>
<p>{{post.content}}</p>
<a href="#" @click.prevent="destroy(post)">Delete this post</a>
<hr />
<section class="comments">
<h3>Comments</h3>
<article v-for="comment in posts.comments" :key="comment.id" class="comments__comment">
<h4>From {{comment.author}}</h4>
<p>{{comment.content}}</p>
</article>
</section>
</article>
</div>
</template>
<script>
import Post from 'data/models/post';
export default {
computed: {
// Returns all posts with reactivity.
posts: () => Post.all()
},
async mounted() {
// Load all posts form the GraphQL API.
await Post.fetch();
},
methods: {
// Deletes the post from Vuex Store and from the server.
async destroy(post) {
post.$deleteAndDestroy();
}
}
}
</script>
这就是从服务器加载博客文章和评论、显示它们并允许用户删除文章所需的全部代码。
GraphQL 查询
上面的代码生成以下 GraphQL 查询fetch
:
query Posts {
posts {
nodes {
id
content
title
publishedAt
comments {
nodes {
id
author
content
publishedAt
postId
}
}
}
}
}
以及以下 GraphQL 突变destroy
:
mutation DeletePost($id: ID!) {
deletePost(id: $id) {
id
}
}
结论
还有很多工作要做:代码在某些地方比较混乱,缺少一些测试,订阅功能尚未实现,配置性还有待提升,文档也尚未完成。但我认为是时候与社区分享我的工作,收集反馈,并希望获得一些贡献,将插件升级到稳定的 1.0.0 版本。
谢谢阅读。
附言:这个副项目即将上线。到时候我会发一篇帖子分享给大家 ;)
文章来源:https://dev.to/phortx/vue-3-graphql-kj6