【AWS Amplify × Vue.js 简单无服务器应用构建教程】第4部分:通过API(Graphql)实现CRUD操作教学
首先
这篇文章是一个由六篇教程构成的系列的第四篇。
① 简介编写
② 利用准备和初始设置编辑
③ 使用Auth实现用户注册和登录功能编辑
④ 使用API(Graphql)实现CRUD编辑
↑↑↑现在在这里↑↑↑
⑤ 使用Storage实现将图片保存到S3编辑
⑥ 使用Hosting发布应用程序和自动部署编辑
在之前的文章中,我们使用了Amplify的Auth功能,实现了一系列的认证功能,包括注册、登录、注销和密码重置等。
这次我们将利用Amplify的API功能来实现一系列的CRUD功能。
CRUD功能指的是对相册的显示、注册、更新和删除等一系列功能。
用AmplifyAPI導入,按照Amplify利用準備・初期設定編中的Amplify機能的利用手順进行操作,即可進行API功能的添加。具體操作如下:
1. 使用AmplifyCLI的add命令進行後端設置的添加。
2. 使用AmplifyCLI的push命令進行後端資源的創建。
3. 在前端實現後端連接代碼。
以3個步驟完成API功能的添加。
使用AmplifyCLI的add命令来添加后端配置。
在终端中执行下列命令:
amplify新增api
当然会有各种各样的问题显示出来,因此我们需要按照下面的方式进行回答。
请选择以下提到的服务之一:→GraphQL
提供API名称:→amplifyvuealbum
选择API的默认授权类型:→Amazon Cognito用户池
您是否想配置GraphQL API的高级设置?→不,我已完成。
您是否有一个标注的GraphQL模式?→没有
选择一个模式模板:→单个对象及其字段(例如,带有ID、名称、描述的“Todo”)
一旦回答问题并完成处理后,将创建几个后端设置文件。提交
这些配置文件中,最重要的是schema.graphql。
它类似于表定义书,用于定义将创建哪些表于数据库中,
每个表拥有哪些列和列的类型,
以及如何定义表之间的关系等。
由于目前已经定义了示例的Todo表,因此需要删除它,并自己编写Album表和Photo表的定义。
表定义将参考①概述部分中构建应用程序规格所示的ER图。
但是,此时不会创建Photo表的s3key列。
这个列将在下一篇文章的存储部分中实现向S3注册图像的功能时添加。
type Album
@model
@auth(rules: [{ allow: owner }]) {
id: ID!
name: String!
photos: [Photo] @connection(keyName: "byAlbum", fields: ["id"])
}
type Photo
@model
@auth(rules: [{ allow: owner }])
@key(name: "byAlbum", fields: ["albumID"]) {
id: ID!
name: String!
albumID: ID!
album: Album @connection(fields: ["albumID"])
}
提交
通过这个schema.graphql的描述,
可以实现许多功能,
但本次我们只使用基本功能,
详细的解释将省略。
以下是基本的描述规则:
· 在type后面写上表名
· 在表下方以”列名:类型”的形式写下列定义
· 使用以”@”开头的”指令”描述,可以增加各种功能
· 写上”@model”,DynamoDB将创建该表
· 写上”@auth”,可以限制能够访问该表数据的用户(本例中,只允许数据创建者访问该数据)
· 写上”@connection”,可以定义表之间的关系
在这个链接中还有其他各种指令,并且提供了多种实用的功能。
使用AmplifyCLI的push命令来创建后端资源。
因此,API的后端设置已经完成,现在我们将在AWS上实际创建API。
执行以下命令:amplify push
由于有各种问题显示出来,所以我会按照以下方式回答。
确定要继续吗?→是的
是否要为新创建的GraphQL API生成代码?→是的
选择代码生成语言→JavaScript
输入graphQL查询、变异和订阅的文件名模式→src\graphql\**\*.js
是否要生成/更新所有可能的GraphQL操作-查询、变异和订阅?→是的
输入最大语句深度[如果您的模式嵌套较深,请增加默认值]→2
等待一会儿,处理完成后,将在AWS上实际创建资源。
本次创建了一些资源,如AppSync和DynamoDB,
所以让我们去AWS上实际确认一下吧。
另外,在此次amplify push之后,会在本地生成src/graphql/queries.js和src/graphql/mutations.js等文件。
这些类似于从前端向API发送请求的方法列表。
如果想创建专辑,请执行mutations.js中的createAlbum函数;
如果想获取专辑列表数据,请执行queries.js中的listAlbums函数。
在这次教程中,您可以不必担心这些描述内容,可以保持默认设置继续进行。
在创建更实用的应用程序时,您需要自定义这些文件的内容。
这个query或mutation不是Amplify独有的规范,而是GraphQL本身的共同规范。如果想详细了解的话,请查阅GraphQL的规范而不是Amplify。
在前端实现与后端的代码协作。
由于我们已经准备好了后端API,所以接下来我们将编写代码以请求该API并实际进行数据的注册和获取。
・相册列表
・相册注册
・相册更新
・相册详细
・照片注册
一口气完成以上操作。
(至于照片注册,在此阶段仅注册名称,照片本身的注册将在下一篇文章中使用存储功能实现。)
・专辑列表
<template>
<div>
<h1>アルバム一覧</h1>
<router-link custom v-slot="{ navigate }" :to="{ name: 'AlbumCreate' }">
<button @click="navigate">Add Album</button>
</router-link>
<table border="1">
<tr v-for="(album, index) in albums" :key="album.id">
<td>{{ album.name }}</td>
<td>
<router-link
custom
v-slot="{ navigate }"
:to="{ name: 'AlbumShow', params: { albumId: album.id } }"
>
<button @click="navigate">Show Album</button>
</router-link>
</td>
<td>
<router-link
custom
v-slot="{ navigate }"
:to="{ name: 'AlbumEdit', params: { albumId: album.id } }"
>
<button @click="navigate">Edit Album</button>
</router-link>
</td>
<td>
<button @click="deleteAlbum(index, album.id)">
Delete Album
</button>
</td>
</tr>
</table>
</div>
</template>
<script>
import { API } from "aws-amplify";
import { listAlbums } from "../../graphql/queries";
import { deleteAlbum } from "../../graphql/mutations";
export default {
name: "AlbumIndex",
async created() {
this.getAlbums();
},
data() {
return {
albums: [],
};
},
methods: {
async getAlbums() {
await API.graphql({
query: listAlbums,
})
.then((result) => {
console.log(result);
this.albums = result.data.listAlbums.items;
})
.catch((error) => {
console.log(error);
});
},
async deleteAlbum(index, albumId) {
if (!confirm("Delete Album?")) return;
await API.graphql({
query: deleteAlbum,
variables: { input: { id: albumId } },
})
.then((result) => {
console.log(result);
this.albums.splice(index, 1);
})
.catch((error) => {
console.log(error);
});
},
},
};
</script>
提交
注册专辑
<template>
<div>
<h1>アルバム登録</h1>
<form @submit.prevent="submitCreate">
<label>Name</label><br />
<input v-model="form.name" placeholder="Enter album name" /><br />
<input type="submit" value="Submit" />
</form>
</div>
</template>
<script>
import { API } from "aws-amplify";
import { createAlbum } from "../../graphql/mutations";
export default {
name: "AlbumCreate",
data() {
return {
form: {
name: "",
},
};
},
methods: {
async submitCreate() {
await API.graphql({
query: createAlbum,
variables: { input: this.form },
})
.then((result) => {
console.log(result);
this.$router.push({ name: "AlbumIndex" });
})
.catch((error) => {
console.log(error);
});
},
},
};
</script>
提交
・专辑更新
<template>
<div>
<h1>アルバム編集</h1>
<form @submit.prevent="submitUpdate">
<label>Name</label><br />
<input v-model="form.name" placeholder="Enter album name" /><br />
<input type="submit" value="Submit" />
</form>
</div>
</template>
<script>
import { API } from "aws-amplify";
import { getAlbum } from "../../graphql/queries";
import { updateAlbum } from "../../graphql/mutations";
export default {
name: "AlbumEdit",
props: {
albumId: String,
},
async created() {
this.getAlbum();
},
data() {
return {
form: {
id: "",
name: "",
},
};
},
methods: {
async getAlbum() {
await API.graphql({
query: getAlbum,
variables: { id: this.albumId },
})
.then((result) => {
console.log(result);
this.form.id = result.data.getAlbum.id;
this.form.name = result.data.getAlbum.name;
})
.catch((error) => {
console.log(error);
});
},
async submitUpdate() {
await API.graphql({
query: updateAlbum,
variables: { input: this.form },
})
.then((result) => {
console.log(result);
this.$router.push({ name: "AlbumIndex" });
})
.catch((error) => {
console.log(error);
});
},
},
};
</script>
提交
・相册的详细信息 de
<template>
<div>
<h1>アルバム詳細</h1>
<h2>{{ album.name }}</h2>
<router-link
custom
v-slot="{ navigate }"
:to="{ name: 'PhotoCreate', params: { albumId: albumId } }"
>
<button @click="navigate">Add Photo</button>
</router-link>
<table border="1">
<tr v-for="(photo, index) in album.photos.items" :key="photo.id">
<td>{{ photo.name }}</td>
<td>
ここに画像表示
</td>
<td>
<button @click="deletePhoto(index, photo)">Delete Photo</button>
</td>
</tr>
</table>
</div>
</template>
<script>
import { API } from "aws-amplify";
import { getAlbum } from "../../graphql/queries";
import { deletePhoto } from "../../graphql/mutations";
export default {
name: "AlbumShow",
props: {
albumId: String,
},
async created() {
this.getAlbum();
},
data() {
return {
album: {
name: null,
photos: []
},
};
},
methods: {
async getAlbum() {
await API.graphql({
query: getAlbum,
variables: { id: this.albumId },
})
.then((result) => {
console.log(result);
this.album = result.data.getAlbum;
})
.catch((error) => {
console.log(error);
});
},
async deletePhoto(index, photo) {
if (!confirm("Delete Photo?")) return;
await API.graphql({
query: deletePhoto,
variables: { input: { id: photo.id } },
})
.then((result) => {
console.log(result);
this.album.photos.items.splice(index, 1);
})
.catch((error) => {
console.log(error);
});
},
},
};
</script>
提交
• 将照片注册
• 图片签到
• 注册照片
<template>
<div>
<h1>写真登録</h1>
<form @submit.prevent="submitCreate">
<label>Name</label><br />
<input v-model="form.name" placeholder="Enter photo name" /><br />
<p>ここに画像登録フォーム</p>
<input type="submit" value="Submit" />
</form>
</div>
</template>
<script>
import { API } from "aws-amplify";
import { createPhoto } from "../../graphql/mutations";
export default {
name: "PhotoCreate",
props: {
albumId: String,
},
data() {
return {
form: {
albumID: this.albumId,
name: "",
},
};
},
methods: {
async submitCreate() {
await API.graphql({
query: createPhoto,
variables: { input: this.form },
})
.then((result) => {
console.log(result);
this.$router.push({
name: "AlbumShow",
params: { albumId: this.albumId },
});
})
.catch((error) => {
console.log(error);
});
},
},
};
</script>
提交
顺便说一下,由于在进入次层页面后无法返回上层页面,我们将在屏幕上方添加一个“TOP”按钮。
<div v-if="isSignedIn">
<amplify-greetings :username="this.$store.state.user.username"></amplify-greetings>
+ <router-link custom v-slot="{ navigate }" :to="{ name: 'AlbumIndex' }">
+ <button @click="navigate">TOP</button>
+ </router-link>
</div>
提交
这样一来,CRUD功能基本上已经完成了。
虽然省略了各页面代码的详细解释,
但只简单介绍一下要点。
要在Vue中使用Amplify的API,需要以下3个步骤:
1. 导入API模块
2. 导入要使用的查询
3. 将查询和所需参数传递给API模块并执行。
让我们以一个简单的例子来看看 src/views/album/Create.vue。
1. 导入API模块
这是代码部分。
从 “aws-amplify” 导入 { API }。
导入要使用的查询
这是代码。
从“../../graphql/mutations”中导入{ createAlbum }。
在这个页面上,我们要进行相册注册,所以导入 createAlbum。
如果想获取相册列表,导入listAlbums。
如果想删除相册,导入deleteAlbum。
将查询和所需的参数传递给API模块进行执行。
通过在 methods 中的 submitCreate() 中的这段代码来执行API。
API.graphql({
query: createAlbum,
variables: { input: this.form },
})
只需将之前导入的API模块中的graphql方法,以使用的查询(之前导入的查询)和所需的参数作为参数传递。
通过参数传递的 this.form 中包含了在屏幕上输入的表单内容。
这个API执行代码的基本形式是,包括获取列表、注册、更新、删除等操作都是一样的。
只需在每个屏幕上的适当时机执行此API执行代码。
在相册列表页面上,在屏幕显示时使用 created() 执行获取列表API。
在相册注册、更新页面上,在表单发送按钮点击时执行注册、更新API。
我認為這次新增的每個頁面的程式碼,除了上述的API執行區域之外,其餘部分都只使用了Vue的基礎描述,所以只要閱讀程式碼,理解起來應該並不困難。
由于除了图片注册功能外,其余功能已基本可用,
让我们在每个界面上实际注册数据并确认显示。
※将图片注册到S3会在下一个Storage功能部分实施。
这个教程应用程序中没有包含验证处理等功能,所以即使表单为空,也可以进行数据注册。
关于这一点,请各自在最后尝试添加功能。
*请注意,如果注册空数据,则在数据显示页面可能会出现错误。
请在Chrome开发者工具的控制台选项卡中查看内容,因为每个 API 的响应都被输出到 console.log 中。你可以确认已获取的数据内容,如相册列表等。
最后
使用Amplify的API功能实现了基本的CRUD操作。
这次只使用了最简单易用的功能,
但是在Amplify的API中,可以集成许多便利的功能,
如与Elasticsearch进行协作实现强大的搜索功能,
与Lambda进行协作实现复杂的API逻辑等。
我希望在以后的文章中解释这些应用功能。
在下一篇文章中,我们将实现在Storage中将图像保存到S3的功能。
(在我们继续之前,如果您能给出LGTM(Looks Good to Me)的话,我会很高兴的)
【AWS Amplify × Vue.js 简单无服务器应用构建教程】第5部分 使用Storage实现图像保存到S3