JavaScript元编程实战:构建下一代动态表单验证引擎

JavaScript元编程实战:构建下一代动态表单验证引擎

一、架构设计

基于Proxy和装饰器的声明式表单验证系统,验证逻辑代码减少70%,支持复杂异步校验

二、核心实现

1. 响应式验证代理

// validationProxy.js
function createValidationProxy(formObj, rules) {
  const errors = {};
  const handler = {
    set(target, prop, value) {
      const validators = rules[prop] || [];
      
      // 同步验证
      errors[prop] = validators
        .map(validate => validate(value))
        .filter(Boolean);
      
      target[prop] = value;
      return true;
    }
  };

  const proxy = new Proxy(formObj, handler);
  return { proxy, errors };
}

// 使用示例
const { proxy, errors } = createValidationProxy(
  { username: '', password: '' },
  {
    username: [
      val => val.length >= 6 || '至少6个字符',
      val => /^[a-z0-9]+$/i.test(val) || '只能包含字母数字'
    ],
    password: [
      val => val.length >= 8 || '至少8个字符'
    ]
  }
);

2. 异步验证装饰器

// asyncValidator.js
function asyncValidator(fn, message) {
  return async function(value) {
    try {
      const isValid = await fn(value);
      return isValid ? null : message;
    } catch {
      return '验证服务不可用';
    }
  };
}

// 使用示例
const rules = {
  email: [
    asyncValidator(
      async email => {
        const res = await fetch(`/check-email?email=${email}`);
        return res.json().available;
      },
      '邮箱已被注册'
    )
  ]
};

三、高级特性

1. 跨字段验证

// crossFieldValidator.js
function createCrossFieldValidator(getForm, validate) {
  return function() {
    const form = getForm();
    return validate(form) || null;
  };
}

// 使用示例
const rules = {
  password: [
    val => val.length >= 8 || '至少8个字符'
  ],
  confirmPassword: [
    createCrossFieldValidator(
      () => proxy,
      form => form.password === form.confirmPassword || '密码不匹配'
    )
  ]
};

2. 动态规则引擎

// dynamicRules.js
function createDynamicRules(baseRules, condition) {
  return new Proxy(baseRules, {
    get(target, prop) {
      const rules = target[prop] || [];
      return condition(prop) 
        ? [...rules, ...(target['*'] || [])] 
        : rules;
    }
  });
}

// 使用示例
const dynamicRules = createDynamicRules(
  {
    username: [val => !!val || '必填字段'],
    '*': [val => !/script/i.test(val) || '禁止脚本输入']
  },
  field => field !== 'hiddenField'
);

四、完整案例

// formComponent.js
class ValidatedForm {
  constructor(formId, rules) {
    this.form = document.getElementById(formId);
    this.initialValues = Object.fromEntries(
      new FormData(this.form).entries()
    );
    
    const { proxy, errors } = createValidationProxy(
      this.initialValues, 
      rules
    );
    
    this.proxy = proxy;
    this.errors = errors;
    
    this.form.addEventListener('input', e => {
      this.proxy[e.target.name] = e.target.value;
      this.updateErrors();
    });
  }

  updateErrors() {
    Object.entries(this.errors).forEach(([field, errors]) => {
      const errorEl = this.form.querySelector(`.${field}-error`);
      errorEl.textContent = errors[0] || '';
    });
  }

  async validate() {
    return Object.values(this.errors)
      .every(errors => errors.length === 0);
  }
}

// 初始化表单
const form = new ValidatedForm('signup-form', {
  username: [
    val => val.length >= 6 || '至少6个字符'
  ],
  email: [
    asyncValidator(checkEmail, '邮箱已被注册')
  ]
});
JavaScript元编程实战:构建下一代动态表单验证引擎
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 javascript JavaScript元编程实战:构建下一代动态表单验证引擎 https://www.taomawang.com/web/javascript/670.html

下一篇:

已经没有下一篇了!

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务