![](/img/trans.png)
[英]Upgraded jQuery, .on() and document.ready not working with UpdatePanels
[英]jQuery $(document).ready and UpdatePanels?
我正在使用 jQuery 为 UpdatePanel 内的元素连接一些鼠标悬停效果。 事件绑定在$(document).ready
中。 例如:
$(function() {
$('div._Foo').bind("mouseover", function(e) {
// Do something exciting
});
});
当然,这在第一次加载页面时可以正常工作,但是当 UpdatePanel 进行部分页面更新时,它不会运行,并且鼠标悬停效果在 UpdatePanel 内不再起作用。
不仅在第一页加载时,而且每次 UpdatePanel 触发部分页面更新时,在 jQuery 中连接东西的推荐方法是什么? 我应该使用 ASP.NET ajax 生命周期而不是$(document).ready
吗?
UpdatePanel 在更新时完全替换更新面板的内容。 这意味着您订阅的那些事件不再被订阅,因为该更新面板中有新元素。
我为解决此问题所做的工作是在每次更新后重新订阅我需要的事件。 我使用$(document).ready()
进行初始加载,然后使用 Microsoft 的PageRequestManager
(如果您的页面上有更新面板,则可用)重新订阅每个更新。
$(document).ready(function() {
// bind your jQuery events here initially
});
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function() {
// re-bind your jQuery events here
});
PageRequestManager
是一个 javascript 对象,如果页面上有更新面板,它将自动可用。 只要 UpdatePanel 在页面上,您就不需要执行上述代码以外的任何操作来使用它。
如果您需要更详细的控制,此事件传递的参数类似于 .NET 事件传递参数的方式(sender, eventArgs)
,因此您可以查看引发事件的原因并仅在需要时重新绑定。
以下是 Microsoft 文档的最新版本: msdn.microsoft.com/.../bb383810.aspx
根据您的需要,您可能拥有的更好的选择是使用 jQuery 的.on()
。 这些方法比在每次更新时重新订阅 DOM 元素更有效。 但是,在使用此方法之前请阅读所有文档,因为它可能会也可能不会满足您的需求。 有很多 jQuery 插件使用.delegate()
或.on()
重构是不合理的,所以在这些情况下,你最好重新订阅。
<script type="text/javascript">
function BindEvents() {
$(document).ready(function() {
$(".tr-base").mouseover(function() {
$(this).toggleClass("trHover");
}).mouseout(function() {
$(this).removeClass("trHover");
});
}
</script>
将要更新的区域。
<asp:UpdatePanel...
<ContentTemplate
<script type="text/javascript">
Sys.Application.add_load(BindEvents);
</script>
*// Staff*
</ContentTemplate>
</asp:UpdatePanel>
在 UpdatePanel 中使用 jQuery 进行用户控制
这不是问题的直接答案,但我确实通过阅读我在这里找到的答案将这个解决方案放在一起,我认为有人可能会觉得它有用。
我试图在用户控件中使用 jQuery textarea 限制器。 这很棘手,因为用户控件在 UpdatePanel 内运行,并且在回调中丢失了它的绑定。
如果这只是一个页面,那么这里的答案将直接适用。 但是,用户控件不能直接访问 head 标签,也不能像某些答案所假设的那样直接访问 UpdatePanel。
我最终把这个脚本块放在我的用户控件标记的顶部。 对于初始绑定,它使用 $(document).ready,然后从那里使用 prm.add_endRequest:
<script type="text/javascript">
function BindControlEvents() {
//jQuery is wrapped in BindEvents function so it can be re-bound after each callback.
//Your code would replace the following line:
$('#<%= TextProtocolDrugInstructions.ClientID %>').limit('100', '#charsLeft_Instructions');
}
//Initial bind
$(document).ready(function () {
BindControlEvents();
});
//Re-bind for callbacks
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function() {
BindControlEvents();
});
</script>
所以...只是想有人可能想知道这行得通。
升级到 jQuery 1.3 并使用:
$(function() {
$('div._Foo').live("mouseover", function(e) {
// Do something exciting
});
});
注意:live 适用于大多数活动,但不是全部。 文档中有完整的列表。
你也可以试试:
<asp:UpdatePanel runat="server" ID="myUpdatePanel">
<ContentTemplate>
<script type="text/javascript" language="javascript">
function pageLoad() {
$('div._Foo').bind("mouseover", function(e) {
// Do something exciting
});
}
</script>
</ContentTemplate>
</asp:UpdatePanel>
,因为 pageLoad() 是一个 ASP.NET ajax 事件,每次在客户端加载页面时都会执行该事件。
我的答案?
function pageLoad() {
$(document).ready(function(){
等等
像魅力一样工作,许多其他解决方案都惨遭失败。
这对我有用:
$(document).ready(function() {
// Do something exciting
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function() {
// re-bind your jQuery events here
});
});
我会使用以下方法之一:
将事件绑定封装在一个函数中,并在每次更新页面时运行它。 您始终可以包含与特定元素的事件绑定,以免将事件多次绑定到相同的元素。
使用livequery插件,它基本上会自动为您执行方法一。 您的偏好可能会有所不同,具体取决于您希望对事件绑定进行控制的程度。
当$(document).ready(function (){...})
在页面发布后不起作用时,请在 Asp.page 中使用 JavaScript 函数 pageLoad,如下所示:
<script type="text/javascript" language="javascript">
function pageLoad() {
// Initialization code here, meant to run once.
}
</script>
在这种情况下使用函数 pageLoad() 是非常危险的。 您可能会多次连接事件。 我也会远离 .live() 因为它附加到文档元素并且必须遍历整个页面(缓慢而糟糕)。
到目前为止,我看到的最好的解决方案是在更新面板外部的包装器上使用 jQuery .delegate() 函数并利用冒泡。 除此之外,您始终可以使用 Microsoft 的 Ajax 库来连接处理程序,该库旨在与 UpdatePanels 一起使用。
我遇到了类似的问题,发现最有效的方法是依靠事件冒泡和事件委托来处理它。 事件委托的好处是一旦设置,您不必在 AJAX 更新后重新绑定事件。
我在代码中所做的是在更新面板的父元素上设置一个委托。 此父元素不会在更新时被替换,因此事件绑定不受影响。
有许多优秀的文章和插件可以在 jQuery 中处理事件委托,并且该功能可能会融入 1.3 版本。 我用作参考的文章/插件是:
http://www.danwebb.net/2008/2/8/event-delegation-made-easy-in-jquery
一旦你了解它发生了什么,我想你会发现这是一个更优雅的解决方案,它比每次更新后记住重新绑定事件更可靠。 这还有一个额外的好处,即在页面卸载时为您提供一个取消绑定的事件。
FWIW,我在使用 mootools 时遇到了类似的问题。 重新附加我的事件是正确的举动,但需要在请求结束时完成..eg
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function() {...
如果 beginRequest 导致您获得空引用 JS 异常,请记住一些事情。
干杯
这是一个用于更新面板的很棒的插件:
pageLoad = function () {
$('#div').unbind();
//jquery here
}
pageLoad 函数非常适合这种情况,因为它在初始页面加载和每个 updatepanel 异步回发时运行。 我只需要添加 unbind 方法来使 jquery 在 updatepanel 回发上工作。
http://encosia.com/document-ready-and-pageload-are-not-the-same/
我的回答是基于上面所有专家的评论,但下面是任何人都可以使用的以下代码,以确保在每次回发和每次异步回发时 JavaScript 代码仍将被执行。
就我而言,我在页面中有一个用户控件。 只需将以下代码粘贴到您的用户控件中。
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(EndRequestHandler);
function EndRequestHandler(sender, args) {
if (args.get_error() == undefined) {
UPDATEPANELFUNCTION();
}
}
function UPDATEPANELFUNCTION() {
jQuery(document).ready(function ($) {
/* Insert all your jQuery events and function calls */
});
}
UPDATEPANELFUNCTION();
</script>
每次加载后,更新面板总是用其内置的 Scriptmanager 脚本替换您的 Jquery。 如果你像这样使用 pageRequestManager 的实例方法会更好......
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest)
function onEndRequest(sender, args) {
// your jquery code here
});
它会正常工作...
使用下面的脚本并相应地更改脚本的主体。
<script>
//Re-Create for on page postbacks
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function () {
//your codes here!
});
</script>
回应布赖恩麦凯的回答:
我通过 ScriptManager 将 JavaScript 注入我的页面,而不是将其直接放入 UserControl 的 HTML 中。 就我而言,我需要滚动到在 UpdatePanel 完成并返回后可见的表单。 这在文件后面的代码中。 在我的示例中,我已经在主内容页面上创建了prm变量。
private void ShowForm(bool pShowForm) {
//other code here...
if (pShowForm) {
FocusOnControl(GetFocusOnFormScript(yourControl.ClientID), yourControl.ClientID);
}
}
private void FocusOnControl(string pScript, string pControlId) {
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "focusControl_" + pControlId, pScript, true);
}
/// <summary>
/// Scrolls to the form that is made visible
/// </summary>
/// <param name="pControlId">The ClientID of the control to focus on after the form is made visible</param>
/// <returns></returns>
private string GetFocusOnFormScript(string pControlId) {
string script = @"
function FocusOnForm() {
var scrollToForm = $('#" + pControlId + @"').offset().top;
$('html, body').animate({
scrollTop: scrollToForm},
'slow'
);
/* This removes the event from the PageRequestManager immediately after the desired functionality is completed so that multiple events are not added */
prm.remove_endRequest(ScrollFocusToFormCaller);
}
prm.add_endRequest(ScrollFocusToFormCaller);
function ScrollFocusToFormCaller(sender, args) {
if (args.get_error() == undefined) {
FocusOnForm();
}
}";
return script;
}
Sys.Application.add_load(LoadHandler); //This load handler solved update panel did not bind control after partial postback
function LoadHandler() {
$(document).ready(function () {
//rebind any events here for controls under update panel
});
}
对于在我的情况下的其他任何人,我试图让 jquery 文档就绪函数为 DevExpress ASPxCallbackPanel 工作,但以上(迄今为止)没有任何工作。 这对我有用。
<script>
function myDocReadyFunction(){ /* do stuff */ }
</script>
<dx:ASPxCallbackPanel ID="myCallbackPanel" ... >
<ClientSideEvents EndCallback="function(){ myDocReadyFunction();}">
</ClientSideEvents>
<PanelCollection ...>
</dx:ASPxCallbackPanel>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.