我正在使用jQuery将一些鼠标悬停效果连接到UpdatePanel内的元素。事件绑定在$(document).ready
中。例如:
$(function() {
$('div._Foo').bind("mouseover", function(e) {
// Do something exciting
});
});
当然,这在第一次加载页面时工作正常,但是当UpdatePanel执行部分页面更新时,它不会运行,并且鼠标悬停效果在UpdatePanel内部不再起作用。
建议的方法是什么是在jQuery中连接东西不仅在第一页加载,而且每次UpdatePanel激发部分页面更新?我应该使用ASP.NET ajax生命周期而不是$(document).ready
吗?
答案 0 :(得分:531)
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()
是不合理的,因此在这些情况下,最好重新订阅。
答案 1 :(得分:158)
<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>
答案 2 :(得分:62)
在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>
所以...只是觉得有人可能想知道这有效。
答案 3 :(得分:33)
升级到jQuery 1.3并使用:
$(function() {
$('div._Foo').live("mouseover", function(e) {
// Do something exciting
});
});
注意:live适用于大多数事件,但不是全部。 the documentation中有一个完整的列表。
答案 4 :(得分:20)
您也可以尝试:
<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事件,每次在客户端加载页面时都会执行该事件。
答案 5 :(得分:16)
我的回答?
function pageLoad() {
$(document).ready(function(){
等
像魅力一样,许多其他解决方案都失败了。
答案 6 :(得分:7)
这对我有用:
$(document).ready(function() {
// Do something exciting
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function() {
// re-bind your jQuery events here
});
});
答案 7 :(得分:7)
我会使用以下方法之一:
将事件绑定封装在函数中,并在每次更新页面时运行它。您始终可以包含与特定元素绑定的事件,以免多次将事件绑定到相同的元素。
使用livequery插件,它基本上可以自动执行方法一。您的偏好可能会有所不同,具体取决于您希望对事件绑定进行控制的数量。
答案 8 :(得分:6)
当$(document).ready(function (){...})
在页面回发后无效时,请在Asp.page中使用JavaScript函数pageLoad,如下所示:
<script type="text/javascript" language="javascript">
function pageLoad() {
// Initialization code here, meant to run once.
}
</script>
答案 9 :(得分:6)
function pageLoad()在这种情况下使用非常危险。您可以让事件多次连线。我也会远离.live(),因为它附加到文档元素并且必须遍历整个页面(缓慢而蹩脚)。
到目前为止,我看到的最佳解决方案是在更新面板外部的包装器上使用jQuery .delegate()函数并使用冒泡。除此之外,您总是可以使用专为UpdatePanels设计的Microsoft Ajax库来连接处理程序。
答案 10 :(得分:4)
这是一个用于更新面板的绝佳插件:
答案 11 :(得分:4)
FWIW,我遇到过与mootools类似的问题。重新附加我的事件是正确的举动,但需要在请求结束时完成.eg
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function() {...
如果beginRequest导致您获得空引用JS异常,请记住一些事项。
干杯
答案 12 :(得分:4)
我遇到了类似的问题,发现最好的方法是依靠Event Bubbling和事件委托来处理它。关于事件委托的好处是,一旦设置完成,您就不必在AJAX更新后重新绑定事件。
我在代码中执行的操作是在更新面板的父元素上设置委托。更新时不会替换此父元素,因此事件绑定不受影响。
在jQuery中有许多好的文章和插件来处理事件委托,这个功能可能会被纳入1.3版本。我用来参考的文章/插件是:
http://www.danwebb.net/2008/2/8/event-delegation-made-easy-in-jquery
一旦你了解它发生了什么,我想你会发现这是一个更优雅的解决方案,比每次更新后记住重新绑定事件更可靠。这还有一个额外的好处,即在卸载页面时为您提供一个取消绑定的事件。
答案 13 :(得分:3)
pageLoad = function () {
$('#div').unbind();
//jquery here
}
pageLoad函数非常适合这种情况,因为它在初始页面加载和每个updatepanel异步回发上运行。我只需添加unbind方法,使jquery在updatepanel回发上工作。
http://encosia.com/document-ready-and-pageload-are-not-the-same/
答案 14 :(得分:2)
我的回答基于上面的所有专家评论,但下面是以下代码,任何人都可以使用这些代码来确保每次回发和每次异步回发时,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>
答案 15 :(得分:2)
更新面板始终会将其Jquery替换为内置的Scriptmanager脚本。如果你使用像这样的pageRequestManager的实例方法,它会更好......
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest)
function onEndRequest(sender, args) {
// your jquery code here
});
它会正常工作......
答案 16 :(得分:0)
回应Brian MacKay的回答:
我通过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;
}
答案 17 :(得分:0)
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
});
}
答案 18 :(得分:0)
使用以下脚本,并相应地更改脚本的正文。
<script>
//Re-Create for on page postbacks
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function () {
//your codes here!
});
</script>