Jor*_*ger 4 javascript asp.net asp.net-ajax
我正在构建一个可能包含数十个单独项目的购物车页面.每个项目都有一个可折叠面板,其中包含几个可用于自定义它的表单元素.大多数购物车都包含在UpdatePanel中,这样我就可以在用户进行更改时避免完整的回发.当购物车中有很多商品时,当然有许多回发元素,所有这些元素都包含在原始表单中,即使每个帖子实际上只是由单个元素的更改触发(ChildrenAsTriggers = True).
我发现冗余表单名称/值对的未压缩大小是25K.由于浏览器中的gzip压缩,实际大小可能要小得多(我假设浏览器经常压缩回发值,但没有麻烦来验证这一点 - 任何人都知道肯定吗?)我知道我正在这里有点肛门("优化前的配置文件!")但我真的想找到一种方法来消除这些冗余数据.我提出了以下JavaScript:
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest
(
function(sender, args) {
var elPostBackTrigger = args.get_postBackElement();
// skip the first input element, which is expected to be the ScriptManager's hidden field
removeNonEssentialPostBackValues(document.aspnetForm.getElementsByTagName("input"), elPostBackTrigger, 1);
removeNonEssentialPostBackValues(document.aspnetForm.getElementsByTagName("select"), elPostBackTrigger);
removeNonEssentialPostBackValues(document.aspnetForm.getElementsByTagName("textarea"), elPostBackTrigger);
}
);
function removeNonEssentialPostBackValues(aElements, elPostBackTrigger, iFirstElement) {
if (iFirstElement == undefined)
iFirstElement = 0;
for (var i = iFirstElement; i < aElements.length; ++i) {
if
(
aElements[i] != elPostBackTrigger
&& aElements[i].name
&& aElements[i].name != ''
&& aElements[i].name.indexOf('_') != 0
) {
aElements[i].removeAttribute('name');
aElements[i].disabled = true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们的想法是,如果删除表单元素的"name"属性,它将不再按照HTML规范"成功",ASP.NET应该从回发中省略它.当然你不想搞砸__VIEWSTATE,__ EVENTTARGET,或者真的以下划线开头的东西.并且您不想删除回发触发器本身.
不幸的是,这对通过Firebug捕获的回发值没有影响.看起来,当PageRequestManager触发beginRequest事件时,它已经生成了回发名称/值对.我发现这很奇怪,因为我认为beginRequest事件的主要原因是在回发之前对表单元素进行了小的更改.也许PageRequestManager实际上并不生成名称/值对,而只是预先生成一个列表,其中包含哪些元素?调试到MS JavaScript库很难实现,我想知道是否有人可以在这里启发我.
编辑1:我还尝试禁用表单元素除了删除其名称属性,但它没有帮助.我通过Firebug验证了在beginRequest事件完成之前元素被禁用并删除了名称,但不知何故,ASP.NET仍然将它们全部添加到回发中.
乔丹·里格
我终于绕过了MicrosoftAjaxWebForms.debug.js并验证了PageRequestManager确实在引发beginRequest事件之前生成了post集合.更糟糕的是,集合存储在StringBuilder中的局部变量中,所以即使我愿意访问私有成员,我也无法操纵它.
我找到的解决方案是从代码后面的Page_Load调用ScriptManager.RegisterOnSubmitStatement来设置JavaScript beforePostback()函数.我确认在PageRequestManager开始它的脏工作之前确实调用了这个函数,所以我能够在那里调用removeNonEssentialPostBackValues().
If Not ScriptManager.GetCurrent(Me).IsInAsyncPostBack Then
ScriptManager.RegisterOnSubmitStatement(Me, Me.GetType(), "beforePostback", "beforePostback()")
End If
Run Code Online (Sandbox Code Playgroud)
和JavaScript:
function beforePostback() {
var nlTriggers = document.getElementsByName(document.aspnetForm.__EVENTTARGET.value);
if (nlTriggers && nlTriggers.length > 0) {
var elPostBackTrigger = nlTriggers[0];
}
// skip the first input element, which is expected to be the ScriptManager's hidden field
removeNonEssentialPostBackValues(document.aspnetForm.getElementsByTagName("input"), elPostBackTrigger, 1);
removeNonEssentialPostBackValues(document.aspnetForm.getElementsByTagName("select"), elPostBackTrigger);
removeNonEssentialPostBackValues(document.aspnetForm.getElementsByTagName("textarea"), elPostBackTrigger);
}
Run Code Online (Sandbox Code Playgroud)
通过这段代码,我发现我可以将手工制作的梦魇场景中的回发请求大小从大约34K减少到大约15K.我还验证了重要的表单值仍然传递到页面,并且代码隐藏仍然可以识别哪个元素触发了回发.
显然,这种技术非常严厉,并不适合很多场景.例如,在用户必须编辑多个字段并通过验证的典型Web表单场景中,您不希望这样做,因为您需要发布所有表单值.实际上,这种技术是一种接近客户端接口的简单方法,其中JavaScript只执行执行命令所需的最小服务器调用.我已经在他们的表现非常好之前和之后构建了这样的应用程序,他们开发和维护是乏味的.对于这个项目,我希望尽可能地利用ASP.NET,同时保持高性能.
更新: 我刚刚在IE 8中测试了这个(我一直在使用Firefox 3.6),这是一个非常缓慢的过程来禁用数百/数千个表单元素.与Firefox 3.6不同,它需要1或2秒,甚至不会闪烁.我不禁想到IE 7可能有多慢.我想我现在必须抛弃这种技术,因为为大量IE用户引入的延迟将远远大于由不必要的表单元素额外的20K回发数据引起的延迟.