![](/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.