0

0

使用HTML、CSS和JavaScript实现本地表单验证及DOM操作教程

聖光之護

聖光之護

发布时间:2025-12-12 10:39:42

|

887人浏览过

|

来源于php中文网

原创

使用HTML、CSS和JavaScript实现本地表单验证及DOM操作教程

本教程详细阐述了如何使用htmlcssjavascript在客户端实现本地表单验证,并提供视觉反馈。文章首先分析并解决了queryselectorall返回nodelist时常见的typeerror,然后逐步构建了一个功能完善的验证系统,包括空值检查和电子邮件格式验证。通过结构化的代码示例和最佳实践建议,读者将学会如何有效地操作dom,以提供即时、友好的用户体验。

客户端表单验证基础

在现代Web应用中,客户端表单验证是提升用户体验的关键一环。它能够在数据提交到服务器之前,即时检查用户输入,减少不必要的服务器请求,并立即向用户提供反馈。本教程将指导您如何利用HTML、CSS和JavaScript实现一套基本的本地表单验证机制,包括如何正确处理DOM元素集合以及如何为不同类型的输入字段添加验证规则。

问题分析:理解 TypeError

在最初的尝试中,开发者可能遇到Uncaught TypeError: Cannot read properties of undefined (reading 'remove')这样的错误。这个错误通常发生在尝试对一个不是单个DOM元素的对象(如NodeList或HTMLCollection)调用classList属性时。

考虑以下JavaScript代码片段:

const errorImg = document.querySelectorAll(".error-img");
// ...
if (!inputs.value) { // 这里的inputs也是一个HTMLCollection,直接访问.value是不正确的
    errorImg.classList.remove("hidden"); // 错误发生在这里
}

document.querySelectorAll(".error-img")返回的是一个NodeList,它是一个类似数组的对象,包含了所有匹配选择器的元素。NodeList本身并没有classList属性。classList是单个DOM元素(如Element对象)的属性。当尝试访问一个undefined值的属性时,JavaScript就会抛出TypeError。

立即学习Java免费学习笔记(深入)”;

此外,document.getElementsByTagName("input")返回的是一个HTMLCollection,它也无法直接通过inputs.value来获取所有输入的值。需要遍历这个集合来访问每个输入字段。

解决方案:正确操作DOM元素集合

要解决上述TypeError,我们需要遍历NodeList或HTMLCollection中的每个元素,并对每个元素单独执行操作。

对于NodeList,最常见且推荐的方法是使用forEach方法:

const errorImgs = document.querySelectorAll(".error-img");

// 隐藏所有错误图片
errorImgs.forEach(img => {
    img.classList.add("hidden");
});

// 显示特定错误图片(例如,第一个)
// errorImgs[0].classList.remove("hidden");

构建表单验证系统

现在,我们将结合HTML、CSS和JavaScript,构建一个更完整的表单验证系统。

1. HTML结构准备

确保您的HTML表单包含输入字段和对应的错误提示元素(例如,一个错误图标或文本)。为每个输入字段及其错误提示提供唯一的ID或易于选择的类名。

@@##@@
@@##@@
@@##@@

注意: 我在每个输入字段的父div中添加了form-control类,并在每个输入字段下方添加了small.error-message元素,用于显示文本错误信息。这有助于更灵活地显示错误。

Lessie AI
Lessie AI

一款定位为「People Search AI Agent」的AI搜索智能体

下载

2. CSS样式定义

使用CSS来控制错误图标和错误信息的显示与隐藏。hidden类是关键。

/* 错误图标和错误信息的基本样式 */
.form-control {
    position: relative; /* 确保错误图标能相对于父元素定位 */
    margin-bottom: 20px; /* 为错误信息留出空间 */
}

.form-control input {
    /* ... 现有样式 ... */
    border: solid 0.09rem hsl(246, 25%, 77%); /* 默认边框 */
}

.form-control.error input {
    border-color: hsl(0, 100%, 74%); /* 错误状态下的边框颜色 */
}

.error-img {
    position: absolute;
    top: 50%;
    right: 22px; /* 根据实际布局调整 */
    transform: translateY(-50%);
    pointer-events: none; /* 确保不影响输入框点击 */
}

.error-message {
    color: hsl(0, 100%, 74%);
    font-size: 0.7rem;
    font-style: italic;
    margin-top: 5px;
    display: block; /* 确保错误信息独占一行 */
    text-align: right; /* 靠右对齐 */
    padding-right: 22px; /* 与错误图标对齐 */
}

/* 隐藏元素的通用类 */
.hidden {
    display: none !important;
}

3. JavaScript验证逻辑

我们将编写JavaScript来处理表单提交事件,对每个输入字段进行验证,并根据验证结果显示或隐藏错误提示。

"use strict";

const form = document.querySelector(".form");
const firstNameInput = document.getElementById("firstName");
const lastNameInput = document.getElementById("lastName");
const emailInput = document.getElementById("email");
const passwordInput = document.getElementById("password");
const submitBtn = document.getElementById("submit-btn");

// 辅助函数:显示错误状态
function showError(input, message) {
    const formControl = input.parentElement; // 获取父级div.form-control
    formControl.classList.add("error"); // 添加错误类,改变边框颜色
    const errorImg = formControl.querySelector(".error-img");
    const errorMessage = formControl.querySelector(".error-message");

    if (errorImg) errorImg.classList.remove("hidden");
    if (errorMessage) {
        errorMessage.innerText = message;
        errorMessage.classList.remove("hidden");
    }
}

// 辅助函数:清除错误状态
function clearError(input) {
    const formControl = input.parentElement;
    formControl.classList.remove("error");
    const errorImg = formControl.querySelector(".error-img");
    const errorMessage = formControl.querySelector(".error-message");

    if (errorImg) errorImg.classList.add("hidden");
    if (errorMessage) errorMessage.classList.add("hidden");
}

// 验证必填字段
function checkRequired(inputs) {
    let isValid = true;
    inputs.forEach(input => {
        if (input.value.trim() === "") {
            showError(input, `${getFieldName(input)} 不能为空`);
            isValid = false;
        } else {
            clearError(input);
        }
    });
    return isValid;
}

// 验证电子邮件格式
function checkEmail(input) {
    const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    if (re.test(input.value.trim())) {
        clearError(input);
        return true;
    } else {
        showError(input, "电子邮件格式不正确");
        return false;
    }
}

// 获取字段名称,用于错误信息
function getFieldName(input) {
    // 将id的首字母大写,例如firstName -> First Name
    return input.id.charAt(0).toUpperCase() + input.id.slice(1).replace(/([A-Z])/g, ' $1');
}

// 表单提交事件监听器
form.addEventListener("submit", (e) => {
    e.preventDefault(); // 阻止表单默认提交行为

    // 检查所有必填字段
    const requiredFieldsValid = checkRequired([firstNameInput, lastNameInput, emailInput, passwordInput]);

    // 检查电子邮件格式
    const emailValid = checkEmail(emailInput);

    // 如果所有验证都通过,则可以提交表单(这里只是打印成功信息)
    if (requiredFieldsValid && emailValid) {
        alert("表单验证成功,可以提交!");
        // 实际应用中,这里会发送AJAX请求或执行其他提交逻辑
        // form.submit(); // 如果需要传统表单提交
    }
});

// 实时验证(可选):可以在输入字段失去焦点时进行验证
[firstNameInput, lastNameInput, emailInput, passwordInput].forEach(input => {
    input.addEventListener('blur', () => {
        if (input.value.trim() === "") {
            showError(input, `${getFieldName(input)} 不能为空`);
        } else {
            clearError(input);
            if (input.type === "email") {
                checkEmail(input);
            }
        }
    });
    // 可以在输入时清除错误,但通常在blur或submit时显示错误
    input.addEventListener('input', () => {
        clearError(input);
    });
});

关键点和注意事项

  1. DOM元素选择器:

    • document.querySelector():返回匹配的第一个元素。
    • document.querySelectorAll():返回所有匹配元素的NodeList。
    • document.getElementById():返回具有指定ID的元素(ID应唯一)。
    • document.getElementsByClassName():返回所有匹配类名的HTMLCollection。
    • document.getElementsByTagName():返回所有匹配标签名的HTMLCollection。
    • 当需要操作多个元素时,务必遍历NodeList或HTMLCollection。
  2. classList属性: classList用于操作元素的CSS类。它提供add(), remove(), toggle(), contains()等方法。

  3. 阻止默认行为: e.preventDefault()在事件处理函数中非常重要,特别是对于表单提交事件,它会阻止浏览器执行默认的表单提交动作,允许我们通过JavaScript进行自定义处理。

  4. 用户体验:

    • 即时反馈: 尽可能提供即时验证反馈,例如在用户输入时或字段失去焦点时。
    • 清晰的错误信息: 错误信息应简洁明了,准确指出问题所在。
    • 视觉提示: 使用颜色(如红色边框)、图标或文本来突出显示错误字段。
  5. 服务器端验证: 客户端验证仅用于提升用户体验和减少无效请求。绝不能依赖客户端验证作为唯一的安全措施。所有关键数据都必须在服务器端进行再次验证,以防止恶意用户绕过客户端脚本。

  6. 可访问性(Accessibility): 对于更专业的应用,考虑使用ARIA属性(如aria-invalid、aria-describedby)来增强表单的可访问性,帮助屏幕阅读器用户理解验证状态。

总结

通过本教程,您应该已经掌握了使用HTML、CSS和JavaScript进行客户端表单验证的基本技能。理解NodeList和HTMLCollection与单个DOM元素的区别是避免常见TypeError的关键。结合清晰的验证逻辑和用户友好的视觉反馈,您可以构建出响应迅速、易于使用的Web表单。记住,客户端验证是用户体验的增强,而服务器端验证则是数据安全的基石。

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

556

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

374

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

733

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

477

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

414

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

1011

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

658

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

553

2023.09.20

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

3

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.9万人学习

CSS教程
CSS教程

共754课时 | 21.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号