用React Alert进行客户端验证
Javascript支持一项功能,可以验证用户从Web应用程序发送到Web服务器的数据是否有效。
这个功能让前端开发者有能力在数据被发送到Web服务器之前验证用户的输入数据。
在这篇文章中,我们将看看如何使用npm包react-alert来验证输入数据。react-alert ,在用户输入数据无效的情况下,可以更容易地将错误信息反馈给用户。
前提条件
要继续学习本教程,你需要。
- [Node.js]10.x或更新版本。
- [NPM]5.10或更新版本。
- 对Javascript中条件语句的了解。
- React.js的基本知识。
- DOM操作的基本知识。
概述
在React之前,vanilla JS是客户端验证的首选解决方案。人们需要了解DOM操作和事件处理的基本原理。
这个验证过程的目的是检查用户发送给服务器的数据是否合适。事件监听器将帮助我们监听网页上发生的事件。
这些事件的范围包括点击一个按钮onClick ,鼠标在网页上某个特定元素上的悬停效果onMouseOver ,使用onSubmit ,提交输入表单中的详细信息,以及更多。
在vanilla JS中执行DOM操作并不是什么大问题,因为DOM是可用的。但在React中,DOM是不可用的,而是有一个虚拟的DOM。
虽然在React中操作DOM的方式与vanilla JS相同,但也有一些怪异之处。一个是Document对象在React中是不可用的。这是因为它与Node.js捆绑在一起,而Node.js并不运行在网络浏览器的客户端。
开始使用
为了能够在React中执行客户端验证,让我们从安装必要的npm 依赖项开始。
我将使用Next.js来引导我的React应用程序。因为它的简单性,它的文件夹结构,以及其他许多好处。
你不需要使用Next.js。你也可以。
- 使用[create-react-app]创建一个React应用。
- 或者用[Parcel.js]引导你的React应用。
请随意使用你觉得合适的方法。
要开始使用Next.js,在你的工作区,打开终端并运行以下命令。
npx create-next-app name-of-your-app
这将安装Next.js和创建React应用程序所需的所有依赖项。因为本文的重点是在React中使用react-alert 进行客户端验证。我们还需要将react-alert 包添加到项目所需的依赖项列表中。下面的命令将为我们处理这个问题。
npm install react-alert –save-dev
对JavaScript中的条件语句如何操作有基本的了解,会加快你在项目的客户端编写验证函数的过程。
一个基本的条件语句如下所示,即if 语句。它是JavaScript中最常用的语句之一,它只在传递的参数为真时才执行代码。
if (username) {
console.log(username);
}
上面的代码片段检查了username 这个变量的有效性。如果它没有被定义,一个引用错误将显示在控制台 "username is not defined"。
const username = "Malete";
if (username) {
console.log(username);
}
// Malete is printed on the console.
上面的代码在控制台显示Malete ,因为username 已经定义。
有些情况下,条件语句并没有在大括号的结尾处停止。如果有其他条件需要检查,我们可以将下一个条件语句连锁起来,直到得到所需的结果。
与if 语句并驾齐驱的其他条件语句是else 和else if 。正如它们的命名惯例所暗示的,else 是在没有条件需要检查的时候使用的。而else if 是在有更多条件需要检查时使用的。
这也是我们在本项目中实现客户端验证时要用到的原则。
设置验证脚本
在创建验证脚本之前,让我们看一下应用程序的文件夹结构。这样,在我们进行的过程中,遍历应用程序结构的过程就不会变得混乱或含糊。
|--pages
| |--_app.js
| |--index.js
|--src
| |--container
| |--App
| |--index.js
|--utils
|--checks.js
|--alert-template.js
上面的结构是真实应用结构的一个节选。但是,为了简洁起见,以及我们将与之互动的文件的重要程度,上面的结构符合本文的范围。
上面的结构显示,checks.js 文件位于utils 文件夹内。checks.js 是我们所有客户端验证逻辑的地方。
由于我们要为网络表单交互/编写这些逻辑,我们需要寻找一种方法来针对在客户端接收用户数据的输入元素。幸运的是,浏览器提供了一些DOM API,我们可以用它们来实现这一目标。请看下面的一个例子。
<input type="”text”" name="”fullname”" id="”fullname”" className="”fullname”" />
const fullnameInputField = document.querySelector(“#fullname”)
console.log(fullnameInputField)
上面的代码将HTML代码记录到控制台。你可以通过打开浏览器的开发工具来检查结果。在谷歌chrome上,快捷键ctrl + shift + i ,可以打开控制台。
如果我们通过输入元素的className ,上面的代码段将变为。
const fullnameInputField = document.querySelector(“.fullname”)
请注意,哈希符号
(#)已经变成了句点符号(.),因为我们是通过其className属性来定位该DOM节点。
现在让我们来看看下面的验证片段。
// utils/check.js file
let errMsg;
const validateSignUp = (email, password, confirmPassword, alert) => {
// targeting all form fields
const emailInput = document.querySelector("#email");
const passwordInput = document.querySelector("#pwd");
const confirmPasswordInput = document.querySelector("#pwd_conf");
if (!email) {
alert.error("Please input your email address");
emailInput.focus();
errMsg = false;
} else if (password === "") {
alert.error("Please provide your password!");
passwordInput.focus();
errMsg = false;
} else if (password.value <= 7) {
alert.error("Your password must have 8 characters or greater");
passwordInput.focus();
errMsg = false;
} else if (
typeof password !== "undefined" &&
typeof confirmPassword !== "undefined"
) {
if (password !== confirmPassword) {
alert.error("Passwords don't match");
confirmPasswordInput.focus();
errMsg = false;
}
} else {
alert.success("You've signed up successfully. Proceed to login");
errMsg = true;
}
return errMsg;
};
export default signUpCheck;
我们将在接下来的时间里对每个代码段的作用进行分解。
-
将表单值作为道具传递
上面的片段是一个辅助函数,在输入的表单数据被发送到后端服务器之前对其进行验证。该函数接受电子邮件、密码、confirmPassword和警报作为参数。
let errMsg;
const validateSignUp = (email, password, confirmPassword, alert) => {};
我们将alert 作为参数传递给函数,这样当它被导入到应用程序组件时,我们就可以访问它。其他参数也是如此。
errMsg 变量存储了来自我们验证逻辑的错误信息。这就是为什么我们用let 关键字声明它,所以它可以在代码执行过程中被重新分配到任何其他值。
-
条件性语句
- 第一个条件是检查电子邮件字段是否为空,如果是,则使用
alert.error()方法在用户界面上显示出一个警告错误信息。
alert.error()方法需要一个字符串作为参数。这个字符串将被显示在用户界面上,浏览器确保输入字段处于焦点位置,以便吸引用户的注意力。if (!email) { alert.error("Please input your email address"); emailInput.focus(); errMsg = false; }- 下一个条件是检查用户是否输入了任何密码。如果密码表单字段中没有任何数值,浏览器中就会弹出一个错误。而下一个条件则是检查密码的长度是否有效。
else if (password === "") { alert.error("Please provide your password!"); passwordInput.focus(); errMsg = false; } else if (password.value <= 7) { alert.error("Your password must have 8 characters or greater"); passwordInput.focus(); errMsg = false; }- 下面的条件语句,检查第一个和第二个密码之间是否存在匹配。该逻辑采用了JavaScript中的闭包来执行这个特殊的验证。
else if (typeof password !== "undefined" && typeof confirmPassword !== "undefined") { if (password != confirmPassword) { alert.error("Passwords don't match"); confirmPasswordInput.focus(); errMsg = false; } }它对两个密码字段进行条件执行,以确保它们都不是未定义的,也就是说,它们不是空字段。如果这第一个条件通过,下一个条件就会运行。如果没有,下一个就不会运行。
- 如果所有的条件都被检查了,警报窗口就会出现成功的文字。
- 第一个条件是检查电子邮件字段是否为空,如果是,则使用
使用验证器
现在我们已经设置好了验证脚本,并且已经掌握了脚本中的内容,现在是时候让它进入应用程序本身了。我们将看一下完成这一工作的步骤。
首先,我们需要把验证脚本和 react-alert 依赖关系一起导入到应用组件中。为了简洁起见,我不会对React组件结构做太多解释,因为它是本文的前提条件之一。
// src/App/index.js file
import React from “react”
import { withAlert } from "react-alert";
import validateSignUp from "../../utils/checks";
const SignUp = ({ alert }) => {
const [fullname, setFullName] = React.useState("");
const [email, setEmail] = React.useState("");
const [password, setPassword] = React.useState("");
const [pwdConfirm, setPwdConfrim] = React.useState("");
// handles the submit event once the user clicks on the button
const handleSubmit = (e) => {
e.preventDefault();
const validate = validateSignUp(email, password, pwdConfirm, alert || " ");
if (validate) {
alert.success("You've signed up successfully. Proceed to login");
}
};
return (
<section>
<div>
<form onSubmit={handleSubmit}>
<div>
<p>Email Address</p>
<input
type="email"
name="email"
id="email"
placeholder="youremail@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<p>Enter Password</p>
<input
name="password"
id="pwd"
placeholder="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div>
<p>Confirm Password</p>
<input
name="confirm__pwd"
id="pwd__conf"
placeholder="enter your password again"
value={pwdConfirm}
onChange={(e) => setPwdConfrim(e.target.value)}
/>
<button>Sign up</button>
</div>
</form>
</div>
</section>
);
};
export default withAlert()(SignUp);
看一下handleSubmit 函数,你会注意到signUpCheck 验证器的参数是如何被使用的。在这个函数中,所有的条件都必须满足,才能提交表单。
const validate = validateSignUp(email, password, pwdConfirm, alert ||" ");
if (validate) {
alert.success("You've signed up successfully. Proceed to login");
}
};
-
设置警报模板
这一步涉及到向我们的应用程序提供react-alert 模板API。没有这个,错误信息就不会显示在网页上。让我们先看一下下面的设置。
我们首先要创建一个组件,作为错误信息的容器。在utils 文件夹中,我们将添加警报模板的所有逻辑。
// alert-template.js file
import React from "react";
import { transitions, positions, Provider as AlertProvider } from "react-alert";
const AlertTemplate = ({ message, options }) => {
return (
<div className={options.type === "success" ? "msg-success" : "msg-error"}>
<p>{message}</p>
</div>
);
};
// this component serves as the container
// that holds/displays the error messages due to the validation
// script that runs on all the app components that have an
// input field
const Message = ({ children }) => {
const options = {
position: positions.TOP_RIGHT,
timeout: 3500,
offset: "0px",
transition: transitions.SCALE,
};
return (
<AlertProvider template={AlertTemplate} {...options}>
{children}
</AlertProvider>
);
};
export default Message;
上面的片段显示了一个三元组格式的条件语句。如果options.type 是 "成功",它将className设置为msg-success ,否则将className设置为msg-error 。
msg-success 给警报模板/模版一个绿色背景,而msg-error 给模板添加一个红色背景。
现在让我们继续添加模板作为应用程序组件的父元素。这可以通过编辑_app.js 文件的内容来完成。
// _app.js file
import React from “react”
import Message from "../src/utils/alert-template";
import Head from “next/head”
function App({ Component, pageProps }) {
return (
<React.Fragment>
<Head>
<link rel="icon" href="#" />
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width"
/>
<title>React alert example</title>
</Head>
<Message>
<Component {...pageProps} />
</Message>
</React.Fragment>
);
}
export default App;
我们已经向应用程序组件提供了警报模板。现在让我们把SignUp表单组件导入到应用组件中。pages/index.js
import React from "react";
import SignUp from "../src/container/App";
export default function IndexPage() {
return <SignUp />;
}
收尾工作
你已经注意到我们没有深入研究这个项目的风格。你可以按照你的喜好来设计你的项目。