使用jquery元数据插件和jquery验证插件的主要烦恼

时间:2012-06-27 17:06:07

标签: jquery jquery-validate

我正在使用无处不在的jquery validate plugin进行表单验证。它支持使用metadata plugin添加验证规则来形成元素。

我正在使用此功能。当validate查找这些规则时,它会对元素进行调用:

$(element).metadata()[meta] 

其中meta是存储这些规则的前缀。例如

<input data-validate="{maxLength: 12}" name='foo'/>

将meta的值设置为“validate”以获取这些属性。但这里有一个重大问题!

以下是元数据插件将数据属性解析为json的内容:

var getObject = function(data) {
    if(typeof data != "string") return data;
    data = eval("(" + data + ")"); //oh no!!!!!
    return data;
} 

if ( settings.type == "html5" ) {
    var object = {};
    $( elem.attributes ).each(function() {
        var name = this.nodeName;
        if(name.match(/^data-/)) name = name.replace(/^data-/, '');
        else return true;
        object[name] = getObject(this.nodeValue);
    });
} 

所以最终发生的是元数据解析所有data-*属性并尝试评估内容!一旦包含不包含json的数据属性,这就会破坏内容。

现在的问题是:

似乎元数据和验证都是“经过验证的”插件。这是使用人们刚刚使用的元数据插件的已知副作用吗?

我通常不喜欢修改插件代码来满足我的项目需求,但这似乎应该是:

  • 修复元数据插件,不要盲目评估内容,不要使用eval或
  • 修复了validate插件,使用.data()代替元数据插件

此外,还有其他方法可以修改元数据插件吗

发布赏金编辑: 我应该更清楚,我会对如何发生这种情况的讨论感兴趣。如何在规范的验证插件和我看过的resig编写的插件中都存在如此大的错误。

修复很简单,我已经应用了它(我选择修改验证插件,以便在定义'meta'时使用$ .data) - 我在这里给出的150分是关于为什么这仍然是一个问题的想法(或者也许不是!)

2 个答案:

答案 0 :(得分:7)

正如您所发现的,“错误”(使用eval)取决于元数据插件,而不是验证插件。

您链接到的元数据插件的版本实际上是一个分叉; jQuery团队有official repo。如果您查看commit history,您会发现自2007年以来没有任何真正的代码更新。自2011年4月以来,该插件一直是officially deprecated

(John Resig在2008年7月发表了关于HTML5 data- attributes的博文,jQuery核心的支持到达1.4.3October 2010已发布。)

所以我猜你的问题“这可能发生了怎么回事”的答案就是你不再想要使用这个插件了: - )

更新: "official" repo现在位于“由jQuery Foundation孤立的项目”下。)

对于validate插件,除了demosmeta选项之外,我在文档中找不到任何元数据插件。正在进行添加support for data- attributesdeprecate the metadata plugin的工作,所以希望在下一个版本准备就绪时,最终可以放弃元数据插件。

答案 1 :(得分:0)

data = eval("(" + data + ")"); //oh no!!!!

替换它的方法之一
data = $.parseJSON(data); // oh yes!!!

实际上,当您使用.data()方法获取“数据”时,它会尝试解析它,并且做得很好。因此,最好从使用它的元素中检索数据。之后,您将获得一个将连接到节点的缓存对象,并将更快地为您提供属性值。

Here you are这是元数据插件的分叉版本,不会评估他获得的所有内容。你必须知道一件事。你应该像JSON一样引用dict的所有部分,但并不总是用双引号引用。

{'foo': 'bar', "m": true, "b": 1}; // works
{foo: 'bar', m: true, b: 1}; // won`t work