jQuery $(文档).ready和UpdatePanels?
我正在使用jQuery为UpdatePanel中的元素连接一些mouseover效果。 事件绑定在$(document).ready
。 例如:
$(function() { $('div._Foo').bind("mouseover", function(e) { // Do something exciting }); });
当然,第一次加载页面的时候这样做效果不错,但是当UpdatePanel进行了部分页面更新时,它不会运行,并且UpdatePanel中的鼠标hover效果不再起作用。
什么是推荐的方法,不仅在第一页加载,但每次UpdatePanel触发部分页面更新时,在jQuery中布线东西? 我应该使用ASP.NET ajax生命周期而不是$(document).ready
?
UpdatePanel完全replace更新中更新面板的内容。 这意味着您订阅的这些事件不再订阅,因为该更新面板中有新的元素。
我为解决这个问题所做的工作是在每次更新后重新订阅我需要的事件。 我使用$(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)
参数(sender, eventArgs)
所以你可以看到什么引发了事件,只有在需要的时候才重新绑定。
以下是来自Microsoft的最新版本的文档: msdn.microsoft.com/…/bb383810.aspx
根据你的需要,更好的select是使用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进行用户控制
这不是直接回答这个问题,但是我通过阅读我在这里find的答案,把这个解决scheme放在一起,我想有人可能会觉得它有用。
我试图在用户控件中使用jQuery textarea限制器。 这很棘手,因为用户控件在UpdatePanel中运行,并且在callback中丢失了绑定。
如果这只是一个页面,这里的答案将直接应用。 但是,用户控件不能直接访问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 }); });
注意:现场对大部分活动都有效,但不是全部。 文档中有一个完整的列表。
你也可以尝试:
<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(){
等等
像一个魅力工作,其中一些其他解决scheme惨败。
我会使用以下方法之一:
-
在一个函数中封装事件绑定,并在每次更新页面时运行它。 您始终可以将事件绑定到特定的元素,以免将事件绑定到相同的元素上。
-
使用livequery插件,基本上为您自动执行方法一。 您的偏好可能会有所不同,具体取决于您想要在事件绑定上拥有的控件数量。
这对我工作:
$(document).ready(function() { // Do something exciting var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_endRequest(function() { // re-bind your jQuery events here }); });
函数pageLoad()在这种情况下使用非常危险。 您可以让事件连接多次。 我也将远离.live(),因为它附加到文档元素,并且必须遍历整个页面(慢和糟糕的)。
到目前为止,我所见过的最好的解决scheme是在更新面板外的包装器上使用jQuery .delegate()函数,并使用冒泡。 除此之外,您可以使用微软的Ajax库来连接处理程序,这个库是专门为UpdatePanelsdevise的。
我有类似的问题,发现最好的方式是依靠事件冒泡和事件委托来处理它。 关于事件委托的好处是,一旦安装,您就不必在AJAX更新后重新绑定事件。
我在代码中做的是在更新面板的父元素上设置一个委托。 此父元素在更新中不会被replace,因此事件绑定不受影响。
有许多优秀的文章和插件来处理jQuery中的事件委托,这个特性很可能会被发布到1.3版本中。 我使用的文章/插件是:
http://www.danwebb.net/2008/2/8/event-delegation-made-easy-in-jquery
一旦你明白了发生了什么,我想你会发现这是一个更加优雅的解决scheme,比每次更新之后重新绑定事件更可靠。 这也有一个额外的好处,即在页面卸载时给你一个事件来解除绑定。
FWIW,我遇到了类似的问题wooter。 重新附加我的活动是正确的举措,但需要在请求结束时完成。例如
var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_endRequest(function() {...
只是要记住,如果beginRequest导致你得到null引用JSexception。
干杯
这是一个用于更新面板的好插件:
如果$(document).ready(function (){...})
在页面回发后无效,则在Asp.page中使用JavaScript函数pageLoad,如下所示:
<script type="text/javascript" language="javascript"> function pageLoad() { // Initialization code here, meant to run once. } </script>
pageLoad = function () { $('#div').unbind(); //jquery here }
pageLoad函数适用于这种情况,因为它在初始页面加载和每个updatepanelasynchronous回发上运行。 我只需要添加取消绑定方法,使jquery工作在updatepanel回发。
http://encosia.com/document-ready-and-pageload-are-not-the-same/
我的答案是基于上面的所有专家评论,但下面的代码是任何人都可以用来确保每个回发和每个asynchronous回发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脚本replace您的Jquery。 它更好,如果你使用这样的pageRequestManager的实例方法…
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest) function onEndRequest(sender, args) { // your jquery code here });
它会正常工作…
回应Brian MacKay的回答:
我通过ScriptManager将JavaScript注入到我的页面,而不是直接将其放到UserControl的HTML中。 在我的情况下,我需要滚动到UpdatePanel完成并返回后可见的窗体。 这在代码背后的文件。 在我的示例中,我已经在主内容页面上创build了prmvariables。
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; }