返回介绍

使用 API 路由构建表单

发布于 2024-06-05 21:19:56 字数 11932 浏览 0 评论 0 收藏 0

一个 HTML 表单会导致浏览器刷新页面或跳转到新页面。为了将表单数据发送到 API 端点,就必须要使用 JavaScript 拦截提交的表单。

本节示例向你展示了如何发送表单数据到一个 API 端点,并处理这些数据。

前期准备

  • 一个开启了 SSR (output: ‘server’)模式的项目
  • 安装一个集成的 UI 框架

操作步骤

  1. /api/feedback 上创建一个 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");
      // Validate the data - you'll probably want to do more than this
      if (!name || !email || !message) {
        return new Response(
          JSON.stringify({
            message: "Missing required fields",
          }),
          { status: 400 }
        );
      }
      // Do something with the data, then return a success response
      return new Response(
        JSON.stringify({
          message: "Success!"
        }),
        { status: 200 }
      );
    };
  2. 使用你的 UI 框架创建一个表单组件。每个输入字段都应该有一个描述该输入值的 name 属性。

    请确保表单中包含一个 <button><input type="submit"> 元素,用于提交表单。

    • Preact
    • React
    • Solid
    • Svelte
    • Vue
    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.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>
    ">
  3. 创建一个函数以接受提交事件(submit event),然后将其作为 submit 事件处理器传递给你的表单。

    在函数中:

    • 调用事件的 preventDefault() 方法,以覆盖浏览器的默认提交过程。
    • 创建一个 FormData 对象,并使用 fetch 将其以 POST 请求发送到你的端点。
    • Preact
    • React
    • Solid
    • Svelte
    • Vue
    src/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>
      );
    }
    {responseMessage &&

    {responseMessage}

    });}"> src/components/FeedbackForm.tsx
    import { FormEvent, useState } from "react";
    
    
    export default function Form() {  const [responseMessage, setResponseMessage] = useState("");
      async function submit(e: FormEvent<HTMLFormElement>) {    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 htmlFor="name">
            Name
            <input type="text" id="name" name="name" autoComplete="name" required />
          </label>
          <label htmlFor="email">
            Email
            <input type="email" id="email" name="email" autoComplete="email" required />
          </label>
          <label htmlFor="message">
            Message
            <textarea id="message" name="message" autoComplete="off" required />
          </label>
          <button>Send</button>      {responseMessage && <p>{responseMessage}</p>}
        </form>
      );
    }
    {responseMessage &&

    {responseMessage}

    });}"> 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>
      );
    }
    {response() &&

    {response().message}

    }
    );}"> 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>
    {#if responseMessage}

    {responseMessage}

    {/if}"> 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>

    {{ responseMessage }}

    ">
  4. 在一个页面中导入并包含你的 <FeedbackForm /> 组件。请确认使用了 client:* 指令以确保表单逻辑能在你需要的时候被激活。

    • Preact
    • React
    • Solid
    • Svelte
    • Vue
    src/pages/index.astro
    ---
    import FeedbackForm from "../components/FeedbackForm"
    ---
    <FeedbackForm client:load />
    src/pages/index.astro
    ---
    import FeedbackForm from "../components/FeedbackForm"
    ---
    <FeedbackForm client:load />
    src/pages/index.astro
    ---
    import FeedbackForm from "../components/FeedbackForm"
    ---
    <FeedbackForm client:load />
    src/pages/index.astro
    ---
    import FeedbackForm from "../components/FeedbackForm.svelte"
    ---
    <FeedbackForm client:load />
    src/pages/index.astro
    ---
    import FeedbackForm from "../components/FeedbackForm.vue"
    ---
    <FeedbackForm client:load />

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文