本文提供了使用 Vue 和 GraphQL 构建一个 CRUD APP 的详细步骤,展示了如何安装 Apollo,
如何将它与 Vue.js 集成,以及如何发送查询和修改来读取、创建、更新和删除数据库中的数据。

在本教程中,我们将学习使用 Vue 和 GraphQL 构建一个 CRUD APP。CRUD 是指该 APP 中所包含的创建、读取、更新和删除操作。你可以在 GitHub 上找到这个演示的源代码:
https://github.com/JscramblerBlog/vue-graphql-demo

准备工作

本教程首先需要几项准备工作:

  • 在你的开发的机器上安装 Node.js 和 NPM。你可以从官方网站 下载它们,或者在你的系统中使用 NVM 轻松安装 Node.js。

  • 具备 JavaScript 的知识,熟悉 Vue。

  • 有 GraphQL Server 相关经验。

如果你已经做好这些准备工作,那就让我们一起开始吧。

在服务器中启用 CORS

由于我们在两个不同的本地端口之间发送请求,这两个端口被视为两个独立的域,因此我们需要在服务器中启用跨源资源共享功能(Cross-Origin Resource Sharing,CORS):
https://blog.jscrambler.com/understanding-cors-cross-origin-resource-sharing/

首先,从 GitHub 库中把代码克隆出来:

git clone https://github.com/JscramblerBlog/node-express-graphql-api.git

接着,进入你的项目目录,安装以下相关组件和 cors 模块:

cd node-express-graphql-api
npm install
npm install cors --save

然后打开 index.js 文件,导入 cors 模块:

    const cors = require('cors');
		

接下来,将 cors 中间件添加到 Express app 中:

    const  app  =  express();
    app.use(cors())

最后,启动服务器:

node index.js

这样你的 GraphQL 服务器就运行起来了,可以在http://localhost:4000/地址下访问。

安装 Vue CLI 3

我们需要安装 Vue CLI 来快速生成 Vue 项目并使用这些项目。打开一个新终端并运行以下命令:

npm install -g @vue/cli

在看完这几个字的时间里,你的机器上应该已经完成 @vue/cli v3.8.2的安装了。

创建一个 Vue 项目

使用 Vue CLI,让我们继续创建一个 Vue 项目。回到终端机,执行下列命令:

vue create vue-graphql-demo 

当提示对预置选项进行选择时,你可以简单地选择默认设置。

等待生成项目,运行以下命令启动开发服务器:

cd vue-graphql-demo
npm run serve

这样,你的应用就运行起来了,在 http://localhost:8080/地址下可以访问。

安装 Apollo 客户端

Apollo 是一组实用程序,可以帮助你在 APP 中使用 GraphQL。它以其客户端和服务器而闻名。Apollo 是由 Meteor Development Group开发和维护的:https://www.meteor.io/

打开一个新的终端,进入你的项目文件夹,运行以下命令来安装 Apollo 客户端到你的 Vue 项目中:

npm install --save vue-apollo graphql apollo-boost

Apollo Boost 是一种无需任何手动配置就可以开始使用 Apollo 客户端的方式。它包括一些常见的默认值,比如推荐的 InMemoryCacheHttpLink,它们是以推荐的参数为你进行配置的。这种零配置的方式适合快速开发使用。

在 src/main.js 文件中,添加以下代码来创建 Apollo 客户端的实例,并将其连接到运行于
http://localhost:4000/graphql 的 GraphQL 服务器:

import ApolloClient from "apollo-boost"
    import VueApollo from "vue-apollo"

    const apolloClient = new ApolloClient({
      uri: "http://localhost:4000/graphql"
    })

    Vue.use(VueApollo)
    const apolloProvider = new VueApollo({
      defaultClient: apolloClient,
    })

我们从 apollo-boost 包中导入 Apollo 客户端 ,从 vue-apollo 包中导入 VueApollo。接下来,我们需要创建 Apollo 客户端的一个实例,并传入 GraphQL 端点的 URL。

然后,我们使用 VueApollo 插件将 Apollo 集成到我们的 Vue APP 中。

最后,我们创建了 Apollo Provider,它包含所有 Vue 组件都可以使用的 Apollo Client 实例。

我们现在要做的就是用 apolloProvider 选项将 Apollo Provider 添加到 Vue 实例中:


  new Vue({
      render: h => h(App),
      apolloProvider,
    }).$mount('#app')
		

这样就行了。现在,我们准备在 Vue APP 中使用 Apollo 客户端。

更多信息请参见文档:
https://vue-apollo.netlify.com/guide/installation.html#manual-installation

使用 GraphQL API

将 vue-apollo 添加到 APP 后,所有组件都可以通过 apollo 选项来使用 Apollo。

首先,打开 src/App.vue 组件,并将 data() 函数添加到具有以下变量的导出对象中:

    <script>
    export default {
      name: 'app',
      data(){
        return {
          id: null,
          firstName: '',
          lastName: '',
          email: ''}
      }

我们定义了四个组件变量,分别是 id、firstName、lastName 和 email。这些变量将被绑定到用于创建新联系人的 HTML Form 中。

发送一个 GraphQL 查询来读取数据

接着,从 graphql-tag 包中导入 gql,并将 apollo 对象添加到带有查询的组件中,我们将使用这个查询从 GraphQL API 中读取联系人:

    <script>
    import gql from 'graphql-tag'

    export default {
      name: 'app',
      /* [...] */
      apollo: {
        contacts: gql`query {
          contacts {
            id,
            firstName,
            lastName,
            email
          }
        }`,
      },

gql 是一个 JavaScript 模板文字标签,它将 GraphQL 查询字符串解析到标准的 GraphQL AST 中。可以在 Github 上的官方库中找到更多详细信息:
https://github.com/apollographql/graphql-tag

在这个 apollo 对象中,我们添加了一个 contacts 属性,它将保存 contacts 查询的结果。稍后,我们将使用它在模板中显示联系人。

发送用于CRUD数据的 mutation 查询

接下来,添加 createContact()、updateContact() 和 deleteContact() 三个方法如下:

 methods: {
        createContact(firstName, lastName, email){
          console.log(`Create contact: ${email}`)
          this.$apollo.mutate({
              mutation: gql`mutation createContact($firstName: String!, $lastName: String!, $email: String!){
                createContact(firstName: $firstName, lastName: $lastName, email: $email) {
                  id,
                  firstName,
                  lastName,
                  email}
              }`,
              variables:{
                firstName: firstName,
                lastName: lastName,
                email: email
              }
            }
          )
          location.reload();
        },
        updateContact(id, firstName, lastName, email){
          console.log(`Update contact: # ${id}`)
          this.$apollo.mutate({
              mutation: gql`mutation updateContact($id: ID!, $firstName: String!, $lastName: String!, $email: String!){
                updateContact(id: $id, firstName: $firstName, lastName: $lastName, email: $email)
              `,
              variables:{
                id: id,
                firstName: firstName,
                lastName: lastName,
                email: email
              }
            }
          )
          location.reload();
        },
        deleteContact(id){
          console.log(`Delete contact: # ${id}`)
          this.$apollo.mutate({
              mutation: gql`mutation deleteContact($id: ID!){
                deleteContact(id: $id)
              }`,
              variables:{
                id: id,
              }
            }
          )
          location.reload();
        },    
      }

在这三个方法中,我们使用 this.$apollo.mutate() 方法向 GraphQL Server 发送 mutation 查询,并调用 location.reload() 方法来重新加载页面。

有关发送 mutation 查询的更多信息,请 参阅文档。

接下来,在 methods 对象中添加 selectContact() 和 clearForm() 方法:

        selectContact(contact){
          this.id = contact.id;
          this.firstName = contact.firstName;
          this.lastName = contact.lastName;
          this.email = contact.email;
        },
        clearForm(){
          this.id = null;
          this.firstName = '';
          this.lastName = '';
          this.email = '';
        }

这两个方法被用来从 Table 中选择一个联系人放入 Form,以及清空 Form。

添加模板

现在让我们添加一个 Table 和 Form 来显示、创建、更新和删除联系人。让我们从 HTML Table 开始:

    <template>
      <div id="app">
      <table border='1' width='100%' style='border-collapse: collapse;'>
       <tr>
         <th>First Name</th>
         <th>Last Name</th>
         <th>Email</th>
         <th>Actions</th>
       </tr>

       <tr v-for='contact in contacts'>
         <td>{{ contact.firstName }}</td>
         <td>{{ contact.lastName }}</td>
         <td>{{ contact.email }}</td>
         <td>
          <input type="button" @click="selectContact(contact)" value="Select">
          <input type="button" @click="deleteContact(contact.id)" value="Delete">
         </td> 
       </tr>
     </table>

我们使用 v-for 指令来迭代 Apollo 对象的 contacts 属性,该 Apollo 对象包含从服务器获取的联系人。我们还添加了两个按钮来选择和删除相应的联系人。

接下来,我们将 Form 添加到 Table 里:

    </br>
        <form>
          <label>First Name</label>
          <input type="text" name="firstName" v-model="firstName">
          </br>

          <label>Last Name</label>
          <input type="text" name="lastName" v-model="lastName">
          </br>

          <label>Email</label>
          <input type="email" name="email" v-model="email">
          </br>

          <input v-if="!id" type="button" @click="createContact(firstName, lastName, email)" value="Add">
          <input v-if="id" type="button" @click="updateContact(id, firstName, lastName, email)" value="Update">
          <input type="button" @click="clearForm()" value="Clear">

        </form>

    </div>
    </template>

我们这样就创建了 Form,每个 Form 包含三个输入,它们绑定到组件中声明的 firstName、lastName 和 email 变量。我们还添加了三个按钮,用于创建新联系人、更新选定的联系人和清除该 Form。

这是添加了大量数据后 UI 的截图:

使用 Select 按钮选择联系人后,将载入 Form 内容,这时会出现 Update 按钮,而不是 Add 按钮:

结论

在本教程中,我们学习了如何用 Apollo 客户端来调用 GraphQL API。我们已经了解了如何安装 Apollo,如何将它与 Vue.js 集成,以及如何发送查询和修改来读取、创建、更新和删除数据库中的联系人。

如果你正在构建具有敏感逻辑的 Vue APP,请遵循我们的指南,以保证它们不受代码盗窃和逆向工程的影响:
https://blog.jscrambler.com/how-to-protect-your-vue-js-application-with-jscrambler/

文章来源:
https://mp.weixin.qq.com

英文原文:
https://blog.jscrambler.com/building-a-crud-app-with-vue-and-graphql/?utm_source=echojs.com&utm_medium=referral