ChatGPT解决这个技术问题 Extra ChatGPT

jQuery $(document).ready 和 UpdatePanels?

我正在使用 jQuery 为 UpdatePanel 内的元素连接一些鼠标悬停效果。事件绑定在 $(document).ready 中。例如:

$(function() {    
    $('div._Foo').bind("mouseover", function(e) {
        // Do something exciting
    });    
});

当然,这在第一次加载页面时可以正常工作,但是当 UpdatePanel 进行部分页面更新时,它不会运行,并且鼠标悬停效果在 UpdatePanel 内不再起作用。

不仅在第一页加载时,而且每次 UpdatePanel 触发部分页面更新时,在 jQuery 中连接东西的推荐方法是什么?我应该使用 ASP.NET ajax 生命周期而不是 $(document).ready

试试这个,我想它会解决你的问题codeproject.com/Articles/21962/…

1
14 revs, 2 users 99%

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() 重构是不合理的,所以在这些情况下,您最好重新订阅。


@Dan,从 jQuery 1.7 开始,.delegate() 已被 .on() 取代
@GabyakaG.Petrioli 我意识到它已被取代,但由于这个答案似乎解决了一个常见问题,我想最大限度地与尚未升级的旧版本 jQuery 的兼容性。我之前的回答推荐了 .live(...),它已在 1.7 中正式弃用,可能会在未来的版本中被删除。我特意选择了 .delegate(),因为它已经在 jQuery 中支持了一段时间,而且不太可能很快被删除。但是,对于那些可以使用它的人,我将升级我的答案以提及 .on()
最好在 $(document).ready 中声明并连接 prm var,因为可能尚未声明 Sys(取决于脚本所在的位置)。
@AhmedSamy 不建议再使用 jQuery.delegate() 。它已被 jQuery.on() 取代,这是首选的 API。 delegate() 只是 on() 特定用途的包装器,将来可能会被弃用。我之前提到 delegate() 的评论是在一年前写的,当时 jQuery 1.7(引入了 on() API)刚刚发布。由于 jQuery 1.9 已经发布并且 2.0 测试版正在准备发布,因此最好避免在任何新代码中使用 delegate()
这可行,但 UpdatePanel 在实施后不再进行部分页面更新。我用 Select2 引导下拉列表(以及引导选择)尝试了这个,这破坏了异步(在没有格式化或初始化的常规下拉列表上工作正常 - 但需要一个漂亮的下拉列表)。唯一的解决方案是完全放弃更新面板,而只使用 jquery ajax 代替(MS 只是没有线索)。
B
Barbaros Alp
<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>

适用于 内的 asp:GridView TextBox
这个解决方案的问题在于,虽然它有效,但它会杀死 UpdatePanel 的异步回发 - 使 UpdatePanel 再次无用。 (叹)
B
Brian MacKay

在 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>

所以...只是想有人可能想知道这行得通。


我无法让它为我的生活工作。然后我将它从头部移到页脚,它起作用了。不是积极的,但我认为它需要在我使用的 ScriptManager 之后出现。
在我的情况下,我使用 ScriptManager.RegisterClientScriptBlock 添加脚本,它在定义 Sys 之前添加脚本,所以我最终改用了 RegisterStartupScript(见差异 here
S
Svante Svenson

升级到 jQuery 1.3 并使用:

$(function() {

    $('div._Foo').live("mouseover", function(e) {
        // Do something exciting
    });

});

注意:live 适用于大多数活动,但不是全部。 the documentation 中有完整列表。


使用实时修复更新面板的问题。没有箍需要跳过。
页面加载时需要发生的事情呢?例如斑马条纹表? $('TABLE TR:nth-child(odd)').addClass('alt-row');
只是为了更新,从 jQuery 1.7 开始,现在建议使用 .on() 代替
刚刚在IE7(jQuery 1.5.1 / VS2010项目)中使用live()方法时发现严重失败。在 v3.5 ASP.NET 中的 UpdatePanel 中使用 live() 时,<asp:DropDownList /> 的常规 AutoPostback 会导致 2 次部分回发,而不是预期的 1 次。浏览器发出的额外回发缺少内容(中止)导致Page.IsPostBackfalse (这会杀死我绑定控件中的状态)。我发现罪魁祸首是 live() 方法。我意识到第一次回发将被 UpdatePanel 根据规范中止,但前提是队列中有另一个没有。
D
Daniel Hursan

你也可以试试:

<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 事件,每次在客户端加载页面时都会执行该事件。


pageLoad 在更新面板的每个异步回发上复制事件。
J
Jason Plank

我的答案?

function pageLoad() {

  $(document).ready(function(){

等等

像魅力一样工作,许多其他解决方案都惨遭失败。


非常适合根据文本量在我的 UserControl 中的 UpdatePanel 中调整我的 Listview 中的文本区域的大小。
我努力使 dom jquery 函数在使用更新面板的回发上正常工作,这个解决方案有效,我不必在 2 个场景中复制我的函数调用。这使 jquery 函数和侦听器保持可用。请注意,我将所有脚本和 jquery 库包含在页面底部的 FORM [end] 标记之前。谢谢!!!
E
Eran Galperin

我会使用以下方法之一:

将事件绑定封装在一个函数中,并在每次更新页面时运行它。您始终可以包含与特定元素的事件绑定,以免将事件多次绑定到相同的元素。使用 livequery 插件,它基本上会自动为您执行方法一。您的偏好可能会有所不同,具体取决于您希望对事件绑定进行控制的程度。


N
Norm

在这种情况下使用函数 pageLoad() 是非常危险的。您可能会多次连接事件。我也会远离 .live() 因为它附加到文档元素并且必须遍历整个页面(缓慢而糟糕)。

到目前为止,我看到的最好的解决方案是在更新面板外部的包装器上使用 jQuery .delegate() 函数并利用冒泡。除此之外,您始终可以使用 Microsoft 的 Ajax 库来连接处理程序,该库旨在与 UpdatePanels 一起使用。


E
ErTR

$(document).ready(function (){...}) 在页面发布后不起作用时,请在 Asp.page 中使用 JavaScript 函数 pageLoad,如下所示:

<script type="text/javascript" language="javascript">
function pageLoad() {
// Initialization code here, meant to run once. 
}
</script>

是的,还要检查 isPartialLoad:stackoverflow.com/questions/301473/…
J
Joe Brinkman

我遇到了类似的问题,发现最有效的方法是依靠事件冒泡和事件委托来处理它。事件委托的好处是一旦设置,您不必在 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 异常,请记住一些事情。

干杯


D
Duane
pageLoad = function () {
    $('#div').unbind();
    //jquery here
}

pageLoad 函数非常适合这种情况,因为它在初始页面加载和每个 updatepanel 异步回发时运行。我只需要添加 unbind 方法来使 jquery 在 updatepanel 回发上工作。

http://encosia.com/document-ready-and-pageload-are-not-the-same/


A
Abhishek Shrivastava

我的回答是基于上面所有专家的评论,但下面是任何人都可以使用的以下代码,以确保在每次回发和每次异步回发时 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>

q
quamrana

每次加载后,更新面板总是用其内置的 Scriptmanager 脚本替换您的 Jquery。如果你像这样使用 pageRequestManager 的实例方法会更好......

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest)
    function onEndRequest(sender, args) {
       // your jquery code here
      });

它会正常工作...


一篇旧帖子,但对我有所帮助。我想补充一点:add_endRequest 代码的位置必须在 UpdatePanel 内,因为 Sys.WebForms.PageRequestManager 仅在那时可用。但是,实际功能不需要位于该位置。所以,就我而言,我有一个 script.js 文件,其中包含我想要绑定的代码,包含在一个函数中。在那个 script.js 文件中,我有一个 document.ready 调用,它调用了上述函数。然后,在我的 UpdatePanel 中,我有 add_endRequest 代码,它也调用上述函数。
m
mzonerz

使用下面的脚本并相应地更改脚本的主体。

       <script>
        //Re-Create for on page postbacks
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        prm.add_endRequest(function () {
           //your codes here!
        });
    </script>

f
fujiiface

回应布赖恩麦凯的回答:

我通过 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;
}

T
Tony Dong
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
        });
}

C
Christopher

对于在我的情况下的其他任何人,我试图让 jquery 文档就绪函数为 DevExpress ASPxCallbackPanel 工作,但以上(迄今为止)没有任何工作。这对我有用。

<script>
function myDocReadyFunction(){ /* do stuff */  }
</script>

<dx:ASPxCallbackPanel ID="myCallbackPanel" ... >
    <ClientSideEvents EndCallback="function(){ myDocReadyFunction();}"> 
    </ClientSideEvents>
    <PanelCollection ...>
</dx:ASPxCallbackPanel>