提交大量元素 MVC

Submit large amount of elements MVC

编辑:jqueryval 是罪魁祸首(不显眼吧?)。不确定为什么它会影响任何东西,因为我们在设置的复选框中禁用了它。但是,注释引用会使加载时间不明显。我已经尝试了几次修复,但都没有成功。

这是导致速度变慢的函数,jquery.validate.js

中的第 532 行
elements: function() {
            *snip*
            return $( this.currentForm )
            .find( "input, select, textarea" )
            .not( ":submit, :reset, :image, [disabled], [readonly]" )
            .not( this.settings.ignore )  //performance murderer
            *snip*
        },

*注意 - 我剪掉了之后的过滤器功能,因为在测试中我没有使用它并且速度仍然变慢,所以它并不真正相关。

我还要从验证中删除复选框:

    $.validator.setDefaults({
        ignore: ":hidden, input[type=checkbox]" //do not validate checkboxes
    });

我有一个 mvc 应用程序,它将 post 将大约 2000 多个复选框返回到服务器。这通常不是问题,通过 jquery 选择器 运行 与网站的交互非常好,加载时间也很快。但是,提交会导致某种回流问题,其中检查每个文本框及其标签 offsetHeight 和 offsetWidth。这导致创建和保存编辑的加载时间超过 5 秒。

开始...

结束...

(我很确定它在最后就放弃了,但是还有大约 2000 个事件你可以滚动它几分钟)

初始负载会受到伤害,但随着用户更多地使用网站,这些复选框中的许多将变成 "disabled",我理解这意味着它们将不再 post 返回。不幸的是,禁用这些文本框不会导致元素数量 post 回落。我感觉这与 MVC 相关,但这是代码:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()


    <fieldset>
        <legend><input type="submit" value="Create"/> | @Html.ActionLink("Back to List", "Index", "CatManager")</legend>

        @if (Model.CategoryViewModel.ChildCategoryNodes.Any())
        {
            for (int i = 0; i < Model.CategoryViewModel.ChildCategoryNodes.Count(); i++)
            {
                @Html.HiddenFor(model => model.CategoryViewModel.ChildCategoryNodes[i].Id)
                @Html.HiddenFor(model => model.CategoryViewModel.ChildCategoryNodes[i].Description)
                <label @(Model.CategoryViewModel.ChildCategoryNodes[i].CategoryId != null ? "disabled" : "")>
                    @if (!Model.CategoryViewModel.ChildCategoryNodes[i].AlreadyTaken)
                    {
                       @Html.CheckBoxFor(model => model.CategoryViewModel.ChildCategoryNodes[i].Selected, new Dictionary<string, object> {{"data-id", Model.CategoryViewModel.ChildCategoryNodes[i].Id}, {"data-description", Model.CategoryViewModel.ChildCategoryNodes[i].Description}}) 
                    }
                    else
                    {
                        @Html.CheckBoxFor(model => model.CategoryViewModel.ChildCategoryNodes[i].Selected, new Dictionary<string, object>{{"data-id", Model.CategoryViewModel.ChildCategoryNodes[i].Id}, {"data-description", Model.CategoryViewModel.ChildCategoryNodes[i].Description}, {"disabled","disabled"}})
                    }
                    @Model.CategoryViewModel.ChildCategoryNodes[i].Id - @Model.CategoryViewModel.ChildCategoryNodes[i].Description
                </label>
            }
        }
    </fieldset>
}

有谁知道如何减少post返回的垃圾数量,或者如何避免这种mega-slow偏移回流?

编辑:像往常一样,有人骚扰我,他们认为他们知道这里发生了什么,但他们显然不知道,所以这里有一些示例代码 运行s 在不到一秒的时间内每次在文本框中输入一个字符时,都会对我的 dom 进行操作。

    $("#filter").on("keyup", function() {
        ValidateTextBoxes();
    });

    function ValidateTextBoxes() {
        $("input[type=checkbox]").each(function() {
            var val = $("#filter").val();
            var id = $(this).data("id");
            var description = $(this).data("description");
            if (val != null && id != null && description != null) {
                if (id.toString().indexOf(val.toString()) > -1 || description.toString().toLowerCase().indexOf(val.toString().toLowerCase()) > -1){
                    $(this).parent().show();
                } else {
                    $(this).parent().hide();
                }
            }
        });
    }

非常感谢,请不要再评论元素的数量了。

我将冒着风险尝试为这个问题提供一个有用的答案,即使 OP 不想听。我回复了the last question you posted regarding these same 2k checkboxes,我仍然坚信你试图解决错误的问题。也许这就是为什么这么多人给你的答案你似乎不想听。

在您的上一个问题中,您表示漫长的等待时间让您在调试和开发时非常沮丧。我建议你重新考虑你的 UI,我收到了 "If I wanted help writing a better UI, I would have asked for it" 的声明。您还表示您计划重写 UI,但与此同时,这些浏览器性能问题阻碍了您完成中间工作。

您可以做的一件事是暂时更改您的测试数据或控制器操作,使其只有 returns 20 个复选框而不是 2000 个。这样的事情应该可以帮助您更快地工作,直到您可以重新设计您的用户体验。如果您计划在生产环境中为您的用户在一个页面上呈现 2000 个复选框,预计他们的用户体验会很差。

我不知道关于 jqueryval 的问题的答案,因此请随时对这个答案投反对票。但是我确实知道浏览器 javascript 引擎(尤其是 IE)在尝试扫描和使用它们时会在非常大的 DOM 上阻塞。技术只会带你走这么远,你必须愿意妥协并在中间的某个地方遇到浏览器。

如果您还没有阅读 jqueryval 源代码,我建议您阅读另一件事。

更新:

好像this.settings.ignore的默认值是':hidden',如下图:

$.extend($.validator, {

    defaults: {
        messages: {},
        groups: {},
        rules: {},
        errorClass: "error",
        validClass: "valid",
        errorElement: "label",
        focusInvalid: true,
        errorContainer: $([]),
        errorLabelContainer: $([]),
        onsubmit: true,
        ignore: ":hidden", // HERE
        ignoreTitle: false,
        onfocusin: function( element, event ) {

而不是分叉 jqueryval,看看这样做是否可以提高性能:

$.validator.setDefaults({ ignore: '' });

参考文献是:

asp.net mvc: why is Html.CheckBox generating an additional hidden input

jQuery Validate - Enable validation for hidden fields

如果忽略设置确实是性能杀手,那么我希望将其设置为空字符串应该使过滤选择器短路并让您回到 "normal" 2k+ 复选框(加上 2k+ 隐藏)的性能输入,总共需要 4k+ 个元素来呈现您的所有类别)。

好的,所以...

问题是jqueryval,我们的答案是在提交按钮上添加取消class以专门阻止此页面上的jqueryval,然后在模型进入控制器时使用ValidatorContext来验证模型。

我们将无法 post 返回的属性重新组合(例如,下拉列表的内容),然后 post 将其返回给用户以由普通 mvc 处理验证摘要。

    [HttpPost]
    public ActionResult Create(EditFirstChildCategoryViewModel editFirstChildCategoryViewModel)
    {
        if (!ModelState.IsValid)
        {
            var categories = _categoryDataService.GetRootCategoryModels();

            editFirstChildCategoryViewModel.ExistingCategoryDropDown =
                _selectListFactory.CreateSelectList(categories, RootCategoryValueExpression,
                    RootCategoryTextExpression);

            return View(editFirstChildCategoryViewModel);
        }
        //etc...
    }

用户可以解决任何问题,而我们的糟糕 2000 复选框设计可以正常运行。