提交大量元素 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 复选框设计可以正常运行。
编辑: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 复选框设计可以正常运行。