使用 API 路由构建表单
一个 HTML 表单会导致浏览器刷新页面或跳转到新页面。为了将表单数据发送到 API 端点,就必须要使用 JavaScript 拦截提交的表单。
本节示例向你展示了如何发送表单数据到一个 API 端点,并处理这些数据。
前期准备
标题部分 前期准备操作步骤
标题部分 操作步骤-
使用你的 UI 框架创建一个表单组件。每个输入字段都应该有一个描述该输入值的
name
属性。请确保表单中包含一个
<button>
或<input type="submit">
元素,用于提交表单。Litsrc/components/FeedbackForm.tsx export default function Form() {return (<form><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button></form>);}src/components/FeedbackForm.tsx export default function Form() {return (<form><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button></form>);}src/components/FeedbackForm.tsx export default function Form() {return (<form><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button></form>);}src/components/FeedbackForm.svelte <form><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button></form>src/components/FeedbackForm.vue <template><form><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button></form></template> -
创建一个
post
API 端点,用于接收表单数据。使用request.formData()
处理表单数据。但在你使用表单值之前,请确保对其进行必要的校验。在这个示例中会向客户端发送一个包含响应消息的 JSON 对象。
src/pages/api/feedback.ts import type { APIRoute } from "astro";export const post: APIRoute = async ({ request }) => {const data = await request.formData();const name = data.get("name");const email = data.get("email");const message = data.get("message");// 你可能需要尽可能多地做有关数据校验的步骤if (!name || !email || !message) {return new Response(JSON.stringify({message: "Missing required fields",}),{ status: 400 });}// 这里你可能会与数据进行交互,然后返回一个成功的响应return new Response(JSON.stringify({message: "Success!"}),{ status: 200 });}; -
创建一个函数以接受提交事件(submit event),然后将其作为
submit
事件处理器传递给你的表单。在函数中,调用事件的preventDefault
方法,以覆盖浏览器的默认提交过程。接下来,创建一个
FormData
对象,并使用fetch
将其发送到你的端点。Litsrc/components/FeedbackForm.tsx import { useState } from "preact/hooks";export default function Form() {const [responseMessage, setResponseMessage] = useState("");async function submit(e: SubmitEvent) {e.preventDefault();const formData = new FormData(e.target as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();if (data.message) {setResponseMessage(data.message);}}return (<form onSubmit={submit}><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button>{responseMessage && <p>{responseMessage}</p>}</form>);}src/components/FeedbackForm.tsx import { useState } from "react";export default function Form() {const [responseMessage, setResponseMessage] = useState("");async function submit(e: SubmitEvent) {e.preventDefault();const formData = new FormData(e.target as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();if (data.message) {setResponseMessage(data.message);}}return (<form onSubmit={submit}><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button>{responseMessage && <p>{responseMessage}</p>}</form>);}src/components/FeedbackForm.tsx import { createSignal, createResource, Suspense } from "solid-js";async function postFormData(formData: FormData) {const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();return data;}export default function Form() {const [formData, setFormData] = createSignal<FormData>();const [response] = createResource(formData, postFormData);function submit(e: SubmitEvent) {e.preventDefault();setFormData(new FormData(e.target as HTMLFormElement));}return (<form onSubmit={submit}><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button><Suspense>{response() && <p>{response().message}</p>}</Suspense></form>);}src/components/FeedbackForm.svelte <script lang="ts">let responseMessage: string;async function submit(e: SubmitEvent) {e.preventDefault();const formData = new FormData(e.currentTarget as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();responseMessage = data.message;}</script><form on:submit={submit}><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button>{#if responseMessage}<p>{responseMessage}</p>{/if}</form>src/components/FeedbackForm.vue <script setup lang="ts">import { ref } from "vue";const responseMessage = ref<string>();async function submit(e: Event) {e.preventDefault();const formData = new FormData(e.currentTarget as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();responseMessage.value = data.message;}</script><template><form @submit="submit"><label>Name<input type="text" id="name" name="name" required /></label><label>Email<input type="email" id="email" name="email" required /></label><label>Message<textarea id="message" name="message" required /></label><button>Send</button><p v-if="responseMessage">{{ responseMessage }}</p></form></template>
更多方案
-
状态共享
学习如何使用 Nano Stores 在框架组件之间共享状态
-
添加 RSS 摘要
通过向你的 Astro 网站添加 RSS 摘要让用户来订阅你的内容。
-
Installing a Vite or Rollup plugin
Learn how you can import YAML data by adding a Rollup plugin to your project.
-
使用 API 路由构建表单
了解如何使用 JavaScript 发送表单到 API 路由
-
在 Astro 页面中构建 HTML 表单
了解如何在 Astro 页面中构建 HTML 表单并在你的 frontmatter 中处理提交请求
-
使用 Bun 和 Astro
学习如何在 Astro 网站上使用 Bun。
-
调用服务器端点
了解如何在 Astro 中调用服务器端点
-
校验验证码
了解如何创建一个 API 路由并从客户端进行获取。
-
用 Docker 来构建你的 Astro 网站
了解如何使用 Docker 来构建你的 Astro 网站。
-
为链接添加图标
了解如何安装 rehype 插件并为你 Markdown 文件中的链接添加图标
-
添加 i18n 功能
通过动态路由和内容集合来让你的 Astro 站点支持国际化。
-
Add Last Modified Time
Build a remark plugin to add the last modified time to your Markdown and MDX.
-
添加阅读时间
构建一个 remark 插件并将其添加到你的 Markdown 或 MDX 文件中。
-
在 Astro 组件中共享状态
了解如何通过 Nano Stores 在 Astro 组件中共享状态