Skip to content

Vue—— Vue 3 + Element Plus 表单输入校验和自动格式化工具函数详解

Vue | July 11, 2026


文章链接:https://blog.csdn.net/qq_43201350/article/details/156505250

在前端开发中,表单输入校验和格式化是一个常见但繁琐的任务。本文介绍一套完整的表单输入校验和自动格式化工具函数,帮助开发者提升用户体验并减少重复代码。

技术难点

  1. 如何自动为表单元素添加合适的属性(如最大长度、占位符等)

  2. 实现通用的数据校验机制,支持多种数据类型

  3. 动态监听 DOM 变化,为新添加的元素自动应用规则

  4. 实时显示校验错误信息并高亮错误字段

实现效果

  • 自动为不同类型的输入框添加默认属性

  • 实时校验用户输入并给出友好提示

  • 支持自定义校验规则

  • 无需手动为每个表单元素添加校验逻辑

示例演示

下面是一套完整的表单输入校验和格式化工具函数:

// 表单校验规则定义
const validationRules = {
  // 手机号码校验
  phone: {
    pattern: /^1[3-9]\d{9}$/,
    message: '请输入正确的手机号码'
  },
  
  // 邮箱校验
  email: {
    pattern: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
    message: '请输入正确的邮箱地址'
  },
  
  // 用户名校验(4-16位字母、数字、下划线)
  username: {
    pattern: /^[a-zA-Z0-9_]{4,16}$/,
    message: '用户名必须是4-16位字母、数字或下划线'
  }
};

/**
 * 为输入元素设置默认属性
 * @param {HTMLElement} element - 表单元素
 */
function setInputDefaults(element) {
  const tagName = element.tagName.toLowerCase();
  const type = element.type;

  // 已经处理过的元素跳过
  if (element._processed) return;

  if (tagName === 'input') {
    // 为文本输入框添加默认最大长度和占位符
    if (type === 'text' && !element.hasAttribute('maxlength')) {
      element.setAttribute('maxlength', '100');
      if (!element.hasAttribute('placeholder')) {
        element.setAttribute('placeholder', '请输入内容');
      }
    }
    
    // 为数字输入框添加最大值限制
    if (type === 'number' && !element.hasAttribute('max')) {
      element.setAttribute('max', '999999999');
    }
  }

  if (tagName === 'textarea' && !element.hasAttribute('maxlength')) {
    element.setAttribute('maxlength', '500');
    element.setAttribute('rows', '4');
    if (!element.hasAttribute('placeholder')) {
      element.setAttribute('placeholder', '请输入内容');
    }
  }

  // 标记为已处理
  element._processed = true;
}

/**
 * 显示校验错误信息
 * @param {HTMLElement} element - 表单元素
 * @param {string} message - 错误信息
 */
function showValidationError(element, message) {
  // 移除已有错误提示
  removeValidationError(element);

  // 创建错误提示元素
  const errorDiv = document.createElement('div');
  errorDiv.className = 'validation-error';
  errorDiv.textContent = message;
  errorDiv.style.cssText = `
    color: #ff4d4f;
    font-size: 12px;
    margin-top: 4px;
  `;

  // 高亮错误字段
  element.style.borderColor = '#ff4d4f';

  // 插入错误提示
  element.parentNode.appendChild(errorDiv);
  element._errorElement = errorDiv;
}

/**
 * 移除校验错误信息
 * @param {HTMLElement} element - 表单元素
 */
function removeValidationError(element) {
  if (element._errorElement) {
    element._errorElement.remove();
    element._errorElement = null;
    element.style.borderColor = '';
  }
}

/**
 * 添加输入校验功能
 * @param {HTMLElement} element - 表单元素
 */
function addInputValidation(element) {
  const dataType = element.getAttribute('data-type');
  
  if (!dataType || !validationRules[dataType]) return;

  // 创建校验处理函数
  const validationHandler = (event) => {
    const value = event.target.value.trim();
    
    // 移除之前错误提示
    removeValidationError(element);

    // 空值不校验
    if (!value) return;

    const rule = validationRules[dataType];
    if (!rule.pattern.test(value)) {
      showValidationError(element, rule.message);
    }
  };

  // 绑定事件
  element.addEventListener('blur', validationHandler);
  element.addEventListener('input', validationHandler);
  
  // 保存引用便于清理
  element._validationHandler = validationHandler;
}

/**
 * 初始化表单校验功能
 */
export function initFormValidation() {
  // 使用 MutationObserver 监听 DOM 变化
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.type === 'childList') {
        mutation.addedNodes.forEach((node) => {
          if (node.nodeType === Node.ELEMENT_NODE) {
            // 处理新添加的表单元素
            if (isFormElement(node)) {
              setInputDefaults(node);
              addInputValidation(node);
            }
            
            // 处理子元素中的表单元素
            const formElements = node.querySelectorAll 
              ? node.querySelectorAll('input, textarea')
              : [];
              
            formElements.forEach((element) => {
              setInputDefaults(element);
              addInputValidation(element);
            });
          }
        });
      }
    });
  });

  // 开始观察 DOM 变化
  observer.observe(document.body, {
    childList: true,
    subtree: true
  });

  // 处理已存在的表单元素
  function processExistingElements() {
    const elements = document.querySelectorAll('input, textarea');
    elements.forEach((element) => {
      setInputDefaults(element);
      addInputValidation(element);
    });
  }

  // 页面加载完成后处理现有元素
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', processExistingElements);
  } else {
    processExistingElements();
  }
}

/**
 * 判断是否为表单元素
 * @param {HTMLElement} element - 元素
 * @returns {boolean}
 */
function isFormElement(element) {
  const tagName = element.tagName.toLowerCase();
  return tagName === 'input' || tagName === 'textarea';
}

解决方案

这套工具函数的核心思想是:

  1. 自动属性设置 :通过 setInputDefaults 函数为不同类型的表单元素自动添加合适的默认属性,如最大长度、占位符等。

  2. 灵活校验规则 :通过 validationRules 对象定义各种校验规则,支持扩展自定义规则。

  3. 实时校验反馈 :通过 addInputValidation 函数为表单元素添加失焦和输入事件监听器,实现实时校验。

  4. 动态元素支持 :使用 MutationObserver 监听 DOM 变化,为动态添加的表单元素自动应用校验规则。

  5. 友好的错误提示 :通过 showValidationErrorremoveValidationError 函数提供直观的错误提示和视觉反馈。

使用方式非常简单,只需在应用初始化时调用 initFormValidation() 函数,并在需要校验的表单元素上添加 data-type 属性:

<input type="text" data-type="phone" />
<input type="text" data-type="email" />
<textarea data-type="username"></textarea>

这样就能自动获得完整的表单校验和格式化功能,大大减少了手动编写校验逻辑的工作量。