【问题标题】:jQuery validate large forms - script running slowlyjQuery 验证大型表单 - 脚本运行缓慢
【发布时间】:2011-07-29 08:37:59
【问题描述】:

我正在使用 jQuery Validate 插件 1.8.0 和 jQuery 1.5。适用于中小型表格。对于较大的表单,性能会显着下降(即使在 IE8 和 FF4 中),有时会导致“脚本运行太慢”消息。即使您指定了自定义规则,该插件似乎也会扫描表单中的整个 DOM 以查找要验证的属性和类。有人知道如何完全关闭它吗?还有一个忽略选项,但它仍然会扫描 DOM,跳过那些具有忽略属性的。

这是 ASP.NET 呈现的内容,除了大约 120 行数据。不幸的是,分页结果不是一种选择。

<table id="GridView1">
    <tbody>
        <tr>
            <th scope="col">Header 1</th>
            <th scope="col">Header 2</th>
            <th scope="col">Header 3</th>
            <th scope="col">Header 4</th>
            <th scope="col">Header 5</th>
            <th scope="col">Header 6</th>
            <th style="width: 60px; white-space: nowrap" scope="col">Header 7</th>
            <th style="width: 60px; white-space: nowrap" scope="col">Header 8</th>
        </tr>        
        <tr class="gridRow" jquery1507811088779756411="3">
            <td style="width: 50px" align="middle">
                <span id="GridView1_ctl03_Label1">XXX</span>
            </td>
            <td>
                <span id="GridView1_ctl03_Label2">YYY</span>
            </td>
            <td style="width: 50px" align="middle">
                <span id="GridView1_ctl03_Label3">ZZZ</span>
            </td>
            <td align="middle">
                <select style="width: 70px" id="GridView1_ctl03_Dropdown4" name="GridView1$ctl03$Dropdown4">
                    <option selected value="Y">Y</option>
                    <option value="N">N</option>
                </select>
            </td>
            <td style="width: 50px" align="middle">
                <input id="GridView1_ctl03_hidId1" value="100" type="hidden" name="GridView1$ctl03$hidId1" />
                <input id="GridView1_ctl03_hidId2" value="100" type="hidden" name="GridView1$ctl03$hidId2" />
                <input id="GridView1_ctl03_hidId3" value="100" type="hidden" name="GridView1$ctl03$hidId3" />
                <input id="GridView1_ctl03_hidId4" value="100" type="hidden" name="GridView1$ctl03$hidId4" />
                <select style="width: 40px" id="GridView1_ctl03_Dropdown5" name="GridView1$ctl03$Dropdown5">
                    <option selected value="A">A</option>
                    <option value="B">B</option>
                </select>
            </td>
            <td style="width: 50px" align="middle">
                <span id="GridView1_ctl03_Label6">101</span>
            </td>
            <td align="middle">
                <input style="width: 60px" id="GridView1_ctl03_Textbox8" class="date required"
                    title="Please enter a valid start date." type="text" name="GridView1$ctl03$Textbox8"
                    jquery1507811088779756411="122" />
            </td>
            <td align="middle">
                <input style="width: 60px" id="GridView1_ctl03_Textbox9" class="date"
                    title="Please enter a valid end date." type="text" name="GridView1$ctl03$Textbox9"
                    jquery1507811088779756411="123" />
            </td>
        </tr>
    </tbody>
</table>

【问题讨论】:

  • 向我们展示您的代码、实时链接或demo。这个表格到底有多大?
  • 我输入了一个代码示例(更改了数据和控件名称以保护无辜者)。大约有 120 行数据,我实际上只是验证日期字段。在 IE8 中验证表单大约需要 8-9 秒。

标签: jquery performance jquery-validate


【解决方案1】:

我也一直在努力解决这个问题。通过自定义一些验证,我能够将 IE8 中 80 个验证元素的验证时间从 4100 毫秒减少到 192 毫秒。我将在这里发布我的发现,希望其他人可以受益,也希望 jquery-validate 方面的一些专家会发现我的代码存在问题。

以下是我认为有帮助的一些事情:

  1. 确保您实际上不需要验证的任何内容都没有验证属性。我有一些神秘地出现在元素上 - 我不知道为什么,但我在我的 .cshtml 中对它们进行了硬编码 data-val=false 以防止这种情况发生。
  2. 定义您自己的方法来验证表单。 jQuery 内置的功能做一些事情非常缓慢,您可能不需要它提供的所有灵活性。这是我的 - 使用它产生了巨大的差异(它被称为子集,因为我的表单被拆分为选项卡,并且随着用户的前进,我在每个选项卡 div 上单独调用它)。

    jQuery.validator.prototype.subset = function (container, validateHiddenElements) {
        var ok = true;
        var validator = this;
    
        // Performance hack - cache the value of errors(), and temporarily patch the    function to return the cache
        // (it is restored at the end of this function).
        var errors = this.errors();
        var errorsFunc = this.errors;
        this.errors = function () { return errors; };
    
        $(container.selector + " [data-val=true]").each(function () {
    
            !this.name && validator.settings.debug && window.console && console.error("%o has no name assigned", this);
    
            var tagName = this.tagName.toLowerCase();
            if (tagName == "input" || tagName == "select" || tagName == "textarea") {
                var $this = $(this);
    
                if (!$this.hasClass('doNotValidate') &&
                    (validateHiddenElements || $this.is(':visible'))) {
    
                    if (!validator.element($this)) ok = false;
    
                }
            }
        });
    
        this.errors = errorsFunc;
    
        return ok;
    };
    
  3. 在 validator.settings 上定义您自己的 showErrors 方法。即使没有要显示的错误,内置的也会为每个可验证的输入创建错误消息范围。如果你有很多这些,这会变得很慢,所以你可以添加一些逻辑来避免这种情况。这是我的:

    function showErrorsOverride() {
        var anyElementsNeedUpdate = false;
        for (var i = 0; i < this.errorList.length; i++) {
            if (!$(this.errorList[i].element).hasClass(this.settings.errorClass)) {
            anyElementsNeedUpdate = true;
            }
        }
        for (var i = 0; i < this.successList.length; i++) {
            if ($(this.successList[i]).hasClass(this.settings.errorClass)) {
                anyElementsNeedUpdate = true;
            }
        }
    
    
        if (anyElementsNeedUpdate) 
        {
            // show the usual errors (defaultShowErrors is part of the jQuery validator)
            this.defaultShowErrors();
        }
    }
    

【讨论】:

  • 我应该把这个放在哪里??
  • 在某些选择列表中添加一些data-val=false 对我来说有很大的不同。加载时间从 34 秒缩短到 8 秒。
【解决方案2】:

聚会有点晚了,但对于任何感兴趣的人来说——类似于 Joe 的回答,我发现从 defaultShowErrors() 函数中禁用成功设置会有很大帮助。它似乎所做的只是隐藏有效字段的错误标签,如果您没有任何错误标签,那么这是不必要的开销。在 IE8 中使用 55 个字段将我的表单从约 1.8 秒加速到约 260 毫秒。

$(document).ready(function()
{
    $("form").each(function ()
    {
        $(this).data("validator").settings.success = false;
    })
});

【讨论】:

  • 想向其他人确认此设置显着提高了我的表现。我正在验证 1000 个元素,我的性能(尤其是在 Firefox 中)从 80 多秒提高到大约 15 秒! IE 11 显示出类似的改进。令人失望的是,Chrome 很糟糕。不断收到“Kill Page”消息(截至今天,这是一个已知错误)。对其他网络开发人员的新版 Chrome 也非常非常失望。
  • 嗨,晚会的时候:我正在为同样的问题苦苦挣扎:我应该把这段代码放在哪里?我试图在加载 jquery javascript 后直接放它,但它似乎迟到了。
【解决方案3】:

我们需要更多代码来帮助您。但是遍历 DOM 对象是一项繁重的操作。 也许对于那种大表格,您想使用另一种方法。如果您使用大量组合和文本字段,您可以附加一个事件处理程序(失去焦点),以便您可以将值保存在 javascript 对象中,然后使用该对象获取数据。

【讨论】:

  • 遍历 DOM 确实很繁重 - 如果您指定自定义规则,我认为验证插件不应该这样做。我可以在此表单上手动滚动验证,但我希望它与应用程序的其余部分保持一致。我想我可能必须自己自定义验证脚本。
【解决方案4】:

我们在大型表单中遇到过类似问题,但找到了以下解决方案。现在我们的大型表单(>600 个输入)在大约 10 毫秒内验证。

我已经在这里发布了答案: https://stackoverflow.com/a/23132844/1821717

【讨论】:

    猜你喜欢
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    相关资源
    最近更新 更多