14

我不确定我是否可以问这种问题,但是在 Meta Stackoverflow 上看到这个之后,看起来这种问题是可以的。好吧,关于我的问题:

几个月前,我用 Javascript 编写了一个验证框架。我知道已经存在像jQuery Validation这样的验证框架,但我想采用不同的方法进行验证。当前的方法处理编写 Javascript 代码以对表单元素执行验证。通过查看表单源代码,并不能立即看出每个元素上发生了什么验证。在某种程度上,这可以通过使用指定不同类型验证的 CSS 类来解决。但我觉得即使这也是有限的,因为您无法轻松自定义验证的行为(错误消息等)。我想在 Java 中使用JSR-303 Bean ValidationHibernate Validator做一些基于注释的验证。

由于 HTML5 允许您向元素添加自定义属性,我想我可以利用它来“注释”表单元素以进行验证。所以,基本上,我想出了这个:

<input id = "myInput"
       name = "myInput"
       type = "text"
       class = "regula-validation"
       data-constraints = '@NotEmpty @IsNumeric @Between(min=1, max=5)' />

考虑到这个基本思想,我创建了一个 Javascript 框架:

  • 检查 DOM 中已定义约束的元素并将这些约束绑定到元素
  • 允许创建自定义约束
  • 允许以编程方式绑定约束
  • 验证绑定约束

此外,该框架还具有以下特点:

  • 验证组,类似于 JSR-303 中指定的组
  • 错误消息的插值

一旦我创建了我的框架,我就试图获得反馈并对其进行审查,但我不确定去哪里获得反馈和审查。我写了几篇关于它的博客文章并将其发布到 Digg 和 Reddit(编程部分),但运气不佳。有几个人似乎感兴趣,但我没有得到更多。

最近,在我的工作场所,我们一直在对遗留代码库(JSP 和 servlet)进行现代化改造并将其转移到 Spring MVC 中。当谈到验证时,我将我的框架介绍给了我的高级架构师。我做了一些集成和概念验证,他们似乎很感兴趣,并允许我将其添加到项目中。到目前为止,我只有自己的拙见,认为这将是一种有用的验证方式,所以这让我有信心相信我的想法和框架可能有一些优点。但是,我仍然需要更多的参与和框架。在我发现 Stackoverflow 确实允许这类问题后,我决定将其发布在这里以获得一些建设性的批评、评论和反馈。

因此,事不宜迟,我想介绍Regula。我提供的链接转到 GitHub 上的 wiki,该 wiki 包含该框架的所有文档。您可以从这里下载最新版本 (v1.1.0) 。

期待您的评论。

一些不立即相关的额外信息

我曾经玩弄过将我的框架与 Spring 集成的想法,即将 bean 上的验证注释转换为客户端验证。最近我能够让它工作,即使是验证组(尽管目前不支持客户端组之间的继承关系)。这样,您只需使用验证约束来注释字段属性,客户端验证代码就会自动生成。但是,我是 Spring 新手,所以我的方法可能不是那么干净。我也想得到一些关于这方面的反馈,所以如果有人感兴趣,请告诉我。理想情况下(我希望我不会太自命不凡)我想联系 Spring 人员,看看他们是否对此感兴趣。

4

2 回答 2

7

我已经非常喜欢它了,它使我的 html 保持干净,并且构建自定义验证器的能力很棒。我添加的一件事是绑定验证和提交函数的简写,并将其包装为 jQuery 插件:

if (jQuery) {
    (function($)
    {
        $.regula = function(formId, callback) 
        {
            regula.bind();

            $("#" + formId).submit(function() 
            {
                var validationResults = regula.validate();

                if (validationResults.length > 0)
                {
                    if (callback)
                        callback(validationResults);

                    return false;
                }

                return true;
            });
        };
    })(jQuery);
}

事实上,我刚刚写了一篇关于它的博客,因为我对它的干净和简单印象深刻。我仍然会花时间浏览你的资源,看看你是如何完成它的,但这是一个很好的开始:)

关于集成您的框架,我主要使用 ASP.NET MVC,看看它如何将服务器端验证逻辑转换为客户端约束会很有趣。我可能会在下个月左右查看一些内容。

于 2010-08-13T22:08:30.183 回答
0

我正在做完全不同的方法:使用像 React 或 Angular 这样的现代框架,你总是在 javascript 中的某个地方而不是在 DOM 输入状态中的表单状态(DOM 只是数据的视图层)。而且我认为它应该是这样的,因为无论您使用哪种花哨的组件来构建您的表单,都始终在包含所有状态的对象下方。从这一点对我来说,自然的方法是只使用原始 JSR-303(没有注释)来验证这个对象(因为 JSR-303 为您提供了这种灵活性)并将错误填充回 DOM。让我给你看一个例子:

import React, { Component } from "react";
import ReactDOM from "react-dom";

import validator, {
  Collection,
  All,
  Required,
  Optional,
  NotBlank,
  Length,
  Email
} from "@stopsopa/validator";

class App extends Component {
  constructor(...args) {
    super(...args);
    this.state = {
      data: {
        name: "",
        email: "",
        comments: []
      },
      errors: {},
      validate: false
    };
  }
  onSubmit = async e => {
    e.preventDefault();

    const errors = await validator(
      this.state.data,
      new Collection({
        name: new Required([new NotBlank(), new Length({ min: 3 })]),
        email: new Required([new NotBlank(), new Email()]),
        comments: new All([new NotBlank(), new Length({ min: 10 })])
      })
    );
    this.setState({
      errors: errors.getTree(),
      validate: true
    });

    if (!errors.count()) {
      console.log("send data to server", this.state.data);
    }
  };
  onChange = (name, value) => {
    console.log(name, value);
    this.setState(state => ({
      ...state,
      data: { ...state.data, ...{ [name]: value } }
    }));
  };
  addComment = () =>
    this.setState(state => {
      const comments = state.data.comments;
      comments.push("");
      const newState = { ...state };
      newState.data.comments = comments;
      return newState;
    });
  deleteComment = i =>
    this.setState(state => {
      const newState = { ...state };
      state.data.comments.splice(i, 1);
      return newState;
    });
  editComment = (i, value) => {
    this.setState(state => {
      const newState = { ...state };
      state.data.comments[i] = value;
      return newState;
    });
  };
  render() {
    const s = this.state;
    console.log("state", JSON.stringify(s, null, 4));
    return (
      <form onSubmit={this.onSubmit}>
        <label>
          name:
          <input
            value={s.data.name}
            onChange={e => this.onChange("name", e.target.value)}
          />
        </label>
        {s.validate && s.errors.name && (
          <div className="error">{s.errors.name}</div>
        )}
        <br />
        <label>
          email:
          <input
            value={s.data.email}
            onChange={e => this.onChange("email", e.target.value)}
          />
        </label>
        {s.validate && s.errors.email && (
          <div className="error">{s.errors.email}</div>
        )}
        <div>
          comments:{" "}
          <a onClick={this.addComment} href="javascript:void(0)">
            add
          </a>
          {s.data.comments.map((m, i) => (
            <div style={{ border: "1px solid red" }} key={i}>
              <textarea
                rows="2"
                value={m}
                onChange={e => this.editComment(i, e.target.value)}
              />
              <a
                onClick={() => this.deleteComment(i)}
                href="javascript:void(0)"
              >
                delete
              </a>
              {s.validate && s.errors.comments && s.errors.comments[i] && (
                <div className="error">{s.errors.comments[i]}</div>
              )}
            </div>
          ))}
        </div>
        <br />
        <input type="submit" value="submit" />
      </form>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

生活示例https://codesandbox.io/s/ymwky9603j

于 2018-12-05T16:59:02.290 回答