返回介绍

在 Astro 页面中构建 HTML 表单

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

在 SSR 模式下,Astro 页面既可以显示又可以处理表单。在本节示例中,你可以使用标准的 HTML 表单将数据提交到服务器。你的 frontmatter 脚本将在服务器端处理数据,而不向客户端发送任何 JavaScript。

前期准备

操作步骤

  1. 创建一个包含表单和处理代码的 .astro 页面。例如,你可以添加一个注册页面(registration page):

    src/pages/register.astro
    ---
    ---
    <h1>Register</h1>
  2. 在页面中添加一个 <form> 标签,并给它添加一些 input 标签内容。每个 input 标签都应该有一个 name 属性,用于描述该输入字段的值。

    请确保在表单中包含了 <button><input type="submit"> 元素以提交表单

    src/pages/register.astro
    ---
    ---
    <h1>Register</h1>
    <form>
      <label>
        Username:
        <input type="text" name="username" />
      </label>
      <label>
        Email:
        <input type="email" name="email" />
      </label>
      <label>
        Password:
        <input type="password" name="password" />
      </label>
      <button>Submit</button>
    </form>
    ">
  3. 使用校验属性提供基本的客户端校验功能,即使 JavaScript 被禁用这也能正常工作。

    在这个例子中,

    • required 属性可以阻止在字段为空时提交表单;
    • minlength 属性可以设置输入文本的最小要求长度;
    • type="email" 属性还引入了校验功能,只接受符合有效电子邮件格式的输入。
    src/pages/register.astro
    ---
    ---
    <h1>Register</h1>
    <form>
      <label>
        Username:
        <input type="text" name="username" required />
      </label>
      <label>
        Email:
        <input type="email" name="email" required />
      </label>
      <label>
        Password:
        <input type="password" name="password" required minlength="6" />
      </label>
      <button>Submit</button>
    </form>
    ">
  4. 提交表单将导致浏览器重新请求页面。把表单的数据传输属性 method 改为 POST,表单数据将作为 Request body 的一部分发送,而不是作为 URL 参数发送。

    src/pages/register.astro
    ---
    ---
    <h1>Register</h1>
    <form method="POST">
      <label>
        Username:
        <input type="text" name="username" required />
      </label>
      <label>
        Email:
        <input type="email" name="email" required />
      </label>
      <label>
        Password:
        <input type="password" name="password" required minlength="6" />
      </label>
      <button>Submit</button>
    </form>
    ">
  5. 在 frontmatter 中检查 POST 方法,并使用 Astro.request.formData() 访问表单数据。将其包裹在 try ... catch 块中,以处理未通过表单发送的 POST 请求和 formData 无效的情况。

    src/pages/register.astro
    ---if (Astro.request.method === "POST") {  try {    const data = await Astro.request.formData();    const name = data.get("username");    const email = data.get("email");    const password = data.get("password");    // Do something with the data  } catch (error) {    if (error instanceof Error) {      console.error(error.message);    }  }}
    ---
    <h1>Register</h1>
    <form method="POST">
      <label>
        Username:
        <input type="text" name="username" required />
      </label>
      <label>
        Email:
        <input type="email" name="email" required />
      </label>
      <label>
        Password:
        <input type="password" name="password" required minlength="6" />
      </label>
      <button>Submit</button>
    </form>
    ">
  6. 在服务器端验证表单数据。这应包括和客户端上的相同的验证方式,以防止你的端点被恶意提交,或者支持少数的不具备表单验证功能的早期旧版浏览器。

    此外,还可以进行一些客户端无法完成的验证。例如,该示例检查电子邮件是否已存在于数据库中。

    也可以通过将错误信息存储在一个 errors 对象中,并在模板中访问该对象,将错误消息发送回客户端。

    src/pages/register.astro
    ---
    import { isRegistered, registerUser } from "../../data/users"
    import { isValidEmail } from "../../utils/isValidEmail";
    
    const errors = { username: "", email: "", password: "" };
    if (Astro.request.method === "POST") {
      try {
        const data = await Astro.request.formData();
        const name = data.get("username");
        const email = data.get("email");
        const password = data.get("password");    if (typeof name !== "string" || name.length < 1) {      errors.username += "Please enter a username. ";    }    if (typeof email !== "string" || !isValidEmail(email)) {      errors.email += "Email is not valid. ";    } else if (await isRegistered(email)) {      errors.email += "Email is already registered. ";    }    if (typeof password !== "string" || password.length < 6) {      errors.password += "Password must be at least 6 characters. ";    }
        const hasErrors = Object.values(errors).some(msg => msg)
        if (!hasErrors) {
          await registerUser({name, email, password});
          return Astro.redirect("/login");
        }
      } catch (error) {
        if (error instanceof Error) {
          console.error(error.message);
        }
      }
    }
    ---
    <h1>Register</h1>
    <form method="POST">
      <label>
        Username:
        <input type="text" name="username" />
      </label>  {errors.username && <p>{errors.username}</p>}
      <label>
        Email:
        <input type="email" name="email" required />
      </label>  {errors.email && <p>{errors.email}</p>}
      <label>
        Password:
        <input type="password" name="password" required minlength="6" />
      </label>  {errors.password && <p>{errors.password}</p>}
      <button>Register</button>
    </form>
    ">

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

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

发布评论

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