Appwrite是一个开源且安全的后端,即服务平台,具有数据库函数和其他核心API,用于构建用于Web,Mobile和Flutter开发人员的类似服务器的应用程序。 AppWrite与客户端和服务器端编程语言集成。
Appwrite Cloud提供与AppWrite相同的服务,例如功能,身份验证,数据库,存储等。使用AppWrite Cloud,所有内容都是从专用URL而不是在Docker上运行的本地实例来管理的。
本教程将向您展示如何在NUXTJ中构建创建,读取,更新和删除(CRUD)应用程序,使用AppWrite Cloud和Pink Design适合前端开发人员。
项目概况
在本课程结束时,CRUD应用程序应该看起来像这样:
github和emo
在this repo中检查此项目的完整源代码。另外,尝试演示here。
先决条件
完成本教程需要以下内容:
- 对JavaScript,Vue和CSS的理解
- Node >= 16用于依赖项安装
- 访问AppWrite Cloud帐户
加入并提交appwrite cloud here的请求。
设置appwrite云
登录到AppWrite Cloud,并通过单击“+创建项目”按钮在云实例中创建一个新项目。
ps:确保给项目一个理想的名称。
创建一个数据库
导航到创建的项目,单击窗口左窗格上的数据库,并给您的数据库一个名称。
创建收藏
AppWrite使用集合作为文档容器。通过单击创建的数据库名称,单击创建Collection 按钮并给出集合一个名称。
添加属性
创建字段参数至关重要,因为它们将保存数据库中的所有注册数据。要创建属性,请导航到创建的集合,然后单击属性选项卡。对于本教程,属性如下:
属性键 | 属性类型 | 大小 | 默认值 | 必需 |
---|---|---|---|---|
todo | 字符串 | 255 | - | 是 |
接下来,在集合中选择设置选项卡,然后更新权限以管理用户的访问和权利。
最后,注册您的Web应用程序。单击概述左窗格上的选项卡,然后添加Web应用程序平台。
主机名带有星号(*)确保在开发过程中访问;否则,如果未设置,交叉原始资源共享(CORS)可能会阻止访问网站数据,从而丢弃错误。
脚手架nuxt应用程序
nuxt是建立在VUE之上的渐进开源框架。让S支架使用以下命令:
npx nuxi init todo
按照说明进行操作,并运行像yarn install
这样的提供的命令。此命令将安装所有必需的依赖项。
接下来,导航到项目目录,然后 todos , ****,然后在终端中启动开发服务器:
cd todos && yarn dev
安装依赖项
如前所述,您需要NUXT应用中的这两个依赖项:appwrite和appwrite pink Design。
在您的终端中,运行此命令:
yarn add appwrite
yarn add @appwrite.io/pink
包括appwrite pink中的粉红色
在您看到AppWrite CSS及其图标的动作之前,让我们在应用程序的根目录中创建页面文件夹。之后,创建一个文件,index.vue
,****并添加以下代码。
pages/index.vue
<template>
<p class="heading-level-1">Add tooodooos</p>
</template>
<script setup lang="ts">
import "@appwrite.io/pink";
import "@appwrite.io/pink-icons";
</script>
接下来,在项目的输入点app.vue
中,将组件NuxtWelcome
更改为NuxtPage
:
app.vue
<template>
<NuxtPage />
</template>
在此结果确认AppWrite CSS库正在工作:
项目树目录应该看起来像这样:
.
├── pages
│ └── index.vue
├── public
├── package.json
├── tsconfig.json
├── yarn.lock
├── README.md
├── nuxt.config.js
└── app.vue
构建UI
Todos应用程序的用户界面将展示使用输入字段创建的所有托多斯,并使用编辑和删除图标列出所有播放。
现在,让我们使用称为组件 ,的新目录更新应用程序目录,其中将包括以下文件:AboutTodo.vue
,Header.vue
,ListTodo.vue
和Todos.vue
。另外,在名为about.vue
的页面文件夹中创建另一个文件。
更新的项目树目录:
.
├── components
│ ├── AboutTodo.vue
│ ├── Header.vue
│ ├── ListTodo.vue
│ └── Todos.vue
├── pages
│ ├── about.vue
│ └── index.vue
├── public
├── package.json
├── tsconfig.json
├── yarn.lock
├── README.md
├── nuxt.config.js
└── app.vue
在文件组件中包括以下代码:
components/AboutTodo.vue
<template>
<div class="container">
<h2 class="eyebrow-heading-2">About Tooodooos</h2>
<p class="text" :style="{ 'margin-top': 1 + 'rem' }">
Using Appwrite functions and Appwrite Cloud, adding todos have become
simpler for anyone wanting to create their own. Appwrite as a tool is a
backend-as-a-service platform.
</p>
<p class="text" :style="{ 'margin-top': 1 + 'rem' }">
The technology used to build this app is Nuxt, Appwrite Pink for the
design system, and integrating Appwrite of course.
</p>
</div>
</template>
abouttodo 组件将在单击导航栏中单击“导航到/大约页面”。
。上面的代码使用AppWrite粉红色设计将关于页面的内容集中。该组件中还包括Vue style bindings在<p>
元素中,该元素设置了1REM的最高边距。
components/Header.vue
<template>
<header
class="u-flex u-main-space-between u-cross-center u-position-sticky"
style="--inset-block-start: auto">
<NuxtLink to="/" class="u-bold">Tooodooos</NuxtLink>
<ul class="list">
<li class="list-item">
<span class="text">
<NuxtLink to="/about">About</NuxtLink>
</span>
</li>
</ul>
</header>
</template>
上面的代码片段使用AppWrite的粉红色 display 和 list 元素来设置导航栏。还包括 nuxtlink 组件,分别用于导航到家庭和大约页面。
components/ListTodo.vue
<template>
<div class="u-flex u-main-space-between u-cross-center u-width-full-line">
<span class="text">{{ item }}</span>
<div class="u-cursor-pointer">
<span
class="icon-pencil"
aria-hidden="true"
:style="{ 'margin-right': space + 'em' }"></span>
<span class="icon-trash" aria-hidden="true"></span>
</div>
</div>
</template>
<script setup>
const props = defineProps({
item: String,
});
const space = ref("1");
</script>
上面的代码显示了 props 数组的待办事项列表项目以及粉红色设计的铅笔和垃圾图标。
components/Todos.vue
<template>
<div class="container">
<Header />
<h1 class="heading-level-1" :style="{ 'margin-top': 1 + 'rem' }">
{{ name }}
</h1>
<form
class="form u-width-full-line u-max-width-500 u-flex u-main-center"
:style="{ 'margin-top': 1 + 'em' }">
<ul class="form-list">
<li class="form-item">
<label class="label">Todo</label>
<div class="input-text-wrapper">
<input
class="input-text"
type="text"
placeholder="add new todo"
v-model="input.todo" />
</div>
</li>
</ul>
<button class="button" :style="{ 'margin-top': 1 + 'em' }">
<span class="text">Add todo</span>
</button>
</form>
<div :style="{ 'margin-top': marginTop + 'em' }">
<ul class="list">
<li class="list-item">
<list-todo item="Create API documentation" />
</li>
</ul>
</div>
</div>
</template>
<script setup>
const name = ref("Add tooodooos");
const marginTop = ref("3");
const input = reactive({
todo: "",
});
</script>
以下内容在上面的代码段中发生:
- 在脚本部分中,使用构图API 声明变量
- 在
<template>
中传递这些值 - 导入标题和 list-todo 组件
- 使用粉红色设计中的类并定义了
:style
绑定到元素 - 将项目传递给列表-DODO组件
pages/about.vue
<template>
<div class="container">
<Header />
<about-todo />
</div>
</template>
该代码负责导入 header 和 aid-todo 组件以显示关于页面的内容。
创建环境变量
由于已部署的项目在GitHub上公开可用,因此可以创建一个本地文件.env
,其中包括您所有的秘密键和常数。
在nuxt.js应用中创建环境变量的this guide
发布新的汤do到appwrite云
创建,读取,更新和删除中的create
操作( crud)将使用HTTP协议方法, post ,这可能意味着创建一个新列表,任务,或张贴。此操作将将此请求发送到数据库AppWrite Cloud。
现在,使用以下代码更新 todos 组件:
components/Todos.vue
<template>
<div class="container">
<Header />
<h1 class="heading-level-1" :style="{ 'margin-top': 1 + 'rem' }">
{{ name }}
</h1>
<form
class="form u-width-full-line u-max-width-500 u-flex u-main-center"
:style="{ 'margin-top': 1 + 'em' }"
@submit.prevent="handleInputChange">
<ul class="form-list">
<li class="form-item">
<label class="label">Todo</label>
<div class="input-text-wrapper">
<input
class="input-text"
type="text"
:placeholder="inputError ? 'please enter a todo' : 'add new todo'"
v-model="input.todo" />
</div>
</li>
</ul>
<button class="button" :style="{ 'margin-top': 1 + 'em' }">
<span class="text">Add todo</span>
</button>
</form>
<div :style="{ 'margin-top': marginTop + 'em' }">
<ul class="list">
<li class="list-item">
<list-todo item="Create API documentation" />
</li>
</ul>
</div>
</div>
</template>
<script setup>
import { Client, Databases, ID } from "appwrite";
const client = new Client();
const databases = new Databases(client);
const runtimeConfig = useRuntimeConfig();
client
.setEndpoint(runtimeConfig.public.API_ENDPOINT)
.setProject(runtimeConfig.public.PROJECT_ID);
const name = ref("Add tooodooos");
const marginTop = ref("3");
const input = reactive({
todo: "",
});
const inputError = ref(false);
const create = (data) =>
databases.createDocument(
runtimeConfig.public.DATABASE_ID,
runtimeConfig.public.COLLECTION_ID,
ID.unique(),
data
);
const handleInputChange = () => {
if (!input.todo) {
return (inputError.value = true);
}
create({
todo: input.todo,
}).then(
function (response) {
window.location.reload();
},
function (error) {
console.log(error);
}
);
};
</script>
以下在此代码段中发生:
- 导入AppWrite软件包并初始化Web SDK的新实例
- 使用
useRuntimeConfig()
,您可以访问环境变量 -
inputError
变量设置为false有助于检查用户试图通过绑定:placeholder
属性发送空输入字段的错误 - 带有参数的
create
函数 data 是在appwrite cloud ****中连接属性键, todo 使用指令在<input>
元素中传递的值v-model
- 使用
@submit.prevent
指令传递给<form>
的函数handleInputChange
将在输入字段中将键入值发送到AppWrite Server - 添加了每一个新的todo,页面刷新带有
window.location.reload()
函数
显示所有招待列表
本节使用读取操作。
再次使用此代码更新Todos组件:
components/Todos.vue
<template>
<div class="container">
<Header />
<h1 class="heading-level-1" :style="{ 'margin-top': 1 + 'rem' }">
{{ name }}
</h1>
<form
class="form u-width-full-line u-max-width-500 u-flex u-main-center"
:style="{ 'margin-top': 1 + 'em' }"
@submit.prevent="handleInputChange">
<ul class="form-list">
<li class="form-item">
<label class="label">Todo</label>
<div class="input-text-wrapper">
<input
class="input-text"
type="text"
:placeholder="inputError ? 'please enter a todo' : 'add new todo'"
v-model="input.todo" />
</div>
</li>
</ul>
<button class="button" :style="{ 'margin-top': 1 + 'em' }">
<span class="text">Add todo</span>
</button>
</form>
<div :style="{ 'margin-top': marginTop + 'em' }">
<ul class="list">
<li class="list-item" v-for="item in todos" :key="item.$id">
<list-todo :item="item" />
</li>
</ul>
</div>
</div>
</template>
<script setup>
...
const todos = ref(null);
const getTodo = databases.listDocuments(
runtimeConfig.public.DATABASE_ID,
runtimeConfig.public.COLLECTION_ID
);
onMounted(() => {
getTodo.then(
function (response) {
todos.value = response.documents;
},
function (error) {
console.log(error);
}
);
});
</script>
上面的代码负责以下内容:
-
getTodo
功能负责列出onMounted
lifecycle钩中应用程序中的所有todo项目 - 使用
v-for
指令循环循环,并用 v-bind替换先前的项目道具:item 或:项目 list-todo上的属性 component
更新待办事项
纠正列表项目(TODOS)对于使用 Update 操作的任何CRUD应用程序至关重要。复制 - 此更新的代码:
components/ListTodo.vue
<template>
<div class="u-flex u-main-space-between u-cross-center u-width-full-line">
<span class="text">{{ item.todo }}</span>
<div class="u-cursor-pointer">
<span
class="icon-pencil"
aria-hidden="true"
@click.prevent="showModal = !showModal"
:style="{ 'margin-right': space + 'em' }"></span>
<span class="icon-trash" aria-hidden="true"></span>
</div>
</div>
<div
v-if="showModal"
class="u-z-index-20 u-padding-24"
:style="{
position: 'fixed',
top: '0',
right: 0,
left: 0,
bottom: 0,
'background-color': 'rgba(0, 0, 0, 0.8)',
height: '100vh',
}">
<form
class="form u-width-full-line u-max-width-500 u-flex u-main-center"
@submit.prevent="handleUpdateTodo">
<ul class="form-list">
<li class="form-item">
<label class="label" :style="{ color: 'white' }">Edit todo</label>
<div class="input-text-wrapper">
<input
class="input-text"
type="text"
v-model="item.todo" />
</div>
</li>
</ul>
<button class="button" :style="{ 'margin-top': 1 + 'em' }">
<span class="text">Update todo</span>
</button>
</form>
<div class="u-cursor-pointer">
<span
class="icon-x u-font-size-32"
@click.prevent="showModal = !showModal"
aria-hidden="true"
:style="{
position: 'absolute',
top: '0',
right: '1em',
color: '#fff',
}"></span>
</div>
</div>
</template>
<script setup>
import { Client, Databases } from "appwrite";
const client = new Client();
const databases = new Databases(client);
const runtimeConfig = useRuntimeConfig();
client
.setEndpoint(runtimeConfig.public.API_ENDPOINT)
.setProject(runtimeConfig.public.PROJECT_ID);
const props = defineProps({
item: Object,
});
const space = ref("1");
const showModal = ref(false);
const updateTodo = (database_id, collection_id, document_id, data) =>
databases.updateDocument(database_id, collection_id, document_id, data);
const handleUpdateTodo = () => {
updateTodo(props.item.$databaseId, props.item.$collectionId, props.item.$id, {
todo: props.item.todo,
}).then(
function (response) {
console.log(`${props.item.todo} successfully updated in DB`);
},
function (error) {
console.log("Error updating the document", error.message);
}
);
};
</script>
此代码片段旨在更新文档的唯一ID。使用补丁方法,它仅更新部分数据:
- 可变
showModal
通过单击铅笔图标 填充模态
- 在
handleUpdateTodo
函数中,用键 todo 传递对象,并在 中传递的值,以使用指令, v-model显示确切的数据
删除待办事项清单
此CRUD应用程序的最后一个操作是使用 delete 方法从客户端和服务器中删除数据。
让S以下代码更新 listTodo 组件:
components/ListTodo.vue
<template>
<div class="u-flex u-main-space-between u-cross-center u-width-full-line">
<span class="text">{{ item.todo }}</span>
<div class="u-cursor-pointer">
<span
class="icon-pencil"
aria-hidden="true"
@click.prevent="showModal = !showModal"
:style="{ 'margin-right': space + 'em' }"></span>
<span
class="icon-trash"
aria-hidden="true"
@click.prevent="handleDeleteTodo"></span>
</div>
</div>
<div
v-if="showModal"
class="u-z-index-20 u-padding-24"
:style="{
position: 'fixed',
top: '0',
right: 0,
left: 0,
bottom: 0,
'background-color': 'rgba(0, 0, 0, 0.8)',
height: '100vh',
}">
<form
class="form u-width-full-line u-max-width-500 u-flex u-main-center"
@submit.prevent="handleUpdateTodo">
<ul class="form-list">
<li class="form-item">
<label class="label" :style="{ color: 'white' }">Edit todo</label>
<div class="input-text-wrapper">
<input class="input-text" type="text" v-model="item.todo" />
</div>
</li>
</ul>
<button class="button" :style="{ 'margin-top': 1 + 'em' }">
<span class="text">Update todo</span>
</button>
</form>
<div class="u-cursor-pointer">
<span
class="icon-x u-font-size-32"
@click.prevent="showModal = !showModal"
aria-hidden="true"
:style="{
position: 'absolute',
top: '0',
right: '1em',
color: '#fff',
}"></span>
</div>
</div>
</template>
<script setup>
...
const deleteTodo = (database_id, collection_id, document_id) =>
databases.deleteDocument(database_id, collection_id, document_id);
const handleDeleteTodo = () => {
deleteTodo(
props.item.$databaseId,
props.item.$collectionId,
props.item.$id
).then(
function (response) {
window.location.reload();
},
function (error) {
console.log(error);
}
);
};
</script>
handleDeleteTodo
函数删除了一个带有唯一ID的todo项目,并在@click evert the <span>
delete delete iCON上使用 @click evert。
在这一点上,UI看起来像这样:
结论
本教程向您展示了如何构建todo crud应用程序并将其功能与AppWrite Cloud配对以创建,存储,更新和删除客户端和服务器。