簡體   English   中英

jQuery $(document).ready 和 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
    });

});

我會使用以下方法之一:

  1. 將事件綁定封裝在一個函數中,並在每次更新頁面時運行它。 您始終可以包含與特定元素的事件綁定,以免將事件多次綁定到相同的元素。

  2. 使用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 異常,請記住一些事情。

干杯

這是一個用於更新面板的很棒的插件:

http://updatepanelplugin.codeplex.com/

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM