在Ajax更新(UpdatePanel)后重新绑定jQuery事件

81
我在页面上有几个输入和选项元素,几乎每个元素都附加了一个事件,一旦更改就会更新页面上的一些文本。我使用非常酷的jQuery :)
我还使用Microsoft的Ajax框架,利用UpdatePanel。我之所以这样做,是因为根据某些服务器端逻辑在页面上创建了某些元素。即使可以(通过相当大的努力)重写为仅使用jQuery,我仍然希望使用UpdatePanel,不想解释为什么使用UpdatePanel。
你可能已经猜到了 - 一旦在UpdatePanel上进行回发,jQuery事件就停止工作了。我实际上是预料到这一点的,因为“回发”并不是真正的新回发,因此我的document.ready中绑定事件的代码不会再次触发。通过阅读jQuery帮助库来证实了我的怀疑。
无论如何,完成UpdatePanel更新DOM后,我需要重新绑定控件的问题。最好的解决方案是不需要向页面添加更多的.js文件(jQuery插件),而是能够简单地捕获UpdatePanel的“afterupdating”,在那里我可以调用我的方法重新绑定所有表单元素。

这与此问题非常相似:https://dev59.com/tnVC5IYBdhLWcg3wjx1d - Dan Herbert
9个回答

87

由于您正在使用ASP.NET AJAX,因此您将可以访问pageLoad事件处理程序,该处理程序在每次页面从UpdatePanel进行完整或部分的回发时都会被调用。您只需要将函数放入页面中即可,无需连接。

function pageLoad(sender, args)
{
   if (args.get_isPartialLoad())
   {
       //Specific code for partial postbacks can go in here.
   }
}

1
没问题 - 顺便说一下,这只是其中一种方法。如果您需要更多的灵活性,请查看PageRequestManager类上的endRequest事件。 - Phil Jenkins
太棒了!我用你的pageLoad替换了我的jquery $(document).ready(去掉if块),问题解决了! - Chris
10
注意:页面上只有一个“pageLoad”函数会执行——最后一个定义的。因此,如果需要执行的操作驻留在不同的控件上,则有更简单的方法来实现所需的行为,比如“Sys.Application.add_load”。 - Paulius

23

或者您可以通过 on() 方法查看最新的 jQuery 动态功能。


这对我来说是最好的解决方案,因为我的许多jQuery标记都封装在页面上的几个用户控件中。 - Kyle B.
1
你能发布一个带有日期选择器的示例吗? - Perica Zivkovic
我只是在使用“on”来绑定一个下拉列表,该下拉列表位于一个触发异步提交的面板内。直到我还包括了@Phil Jenkins上面的答案,它才开始工作。我不确定它是异步提交还是完全回传是否有区别,但是在回传后,on.绑定程序无法处理它。 - Casey ScriptFu Pharr

22
Sys.Application.add_load(initSomething);
function initSomething()
{
  // will execute on load plus on every UpdatePanel postback
}

14
自 jQuery 1.7 起,推荐使用 jQuery 的 .on() 语法来完成此操作。
但请确保在 document 对象上设置事件,而不是 DOM 对象本身。例如,这将在 UpdatePanel 后的回发后中断。
$(':input').on('change', function() {...});

因为':inputs'已被重写,所以请改用以下方法:

$(document).on('change', ':input', function() {...});

只要文档存在,任何输入(包括来自UpdatePanel刷新的输入)都会触发更改处理程序。

太棒了!(文档)使用以下内容非常好:$(document).on('click','#tagsAdd',function (),无论我有多少个更新面板,都可以分解页面的内容 :) 谢谢。 - Martin Sansone - MiOEE

9
使用以下代码
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded);

function pageLoaded(sender, args) {
    var updatedPanels = args.get_panelsUpdated();
    // check if Main Panel was updated 
    for (idx = 0; idx < updatedPanels.length; idx++) {
        if (updatedPanels[idx].id == "<%=upMain.ID %>") {
            rebindEventsForMainPanel();
            break;
        }
    }
}

8
你可以使用jQuery和事件委托。基本上,将事件挂钩到容器而不是每个元素,并查询事件目标并根据其运行脚本。
它有多个好处,可以减少代码噪音(无需重新绑定)。它还可以更轻松地处理浏览器内存(DOM中绑定的事件更少)。
快速示例这里jQuery插件可用于简单的事件委托。
附言:我99%确定委派将在下一个版本的jQuery核心中。

5
使用以下代码,您需要验证控件将使用日期选择器:
    <script type="text/javascript" language="javascript">

         Sys.WebForms.PageRequestManager.getInstance().add_endRequest(addDataPicker); 
         function addDataPicker(sender, args)
         {
            var fchFacturacion = document.getElementById('<%= txtFechaFacturacion.ClientID %>');
            if (fchFacturacion != null) {
               $(fchFacturacion).datepicker({ onSelect: function () { }, changeMonth: true, changeYear: true, showOn: 'button', buttonImage: '../Imagenes/calendar.gif', buttonImageOnly: true});}
         } 

    </script>

     <asp:UpdatePanel ID="upEjem" runat="server" UpdateMode="Conditional">
       <ContentTemplate>
              <div id="div1" runat="server" visible="false">
                  <input type="text" id="txtFechaFacturacion" 
                      name="txtFechaFacturacion" visible="true"
                      readonly="readonly" runat="server" />
              </div>
       </ContentTemplate>
     </asp:UpdatePanel>

4

         <script type="text/javascript">
             function pageLoad() {

                 if (Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack()) {


       }

            </script>

        </ContentTemplate>
    </asp:UpdatePanel>

如果您需要在UpdatePanel进行异步PostBack时执行某些代码,可以将这些代码放入“if”语句中。


2
使用jQuery的新“live”方法绑定事件。它将为所有当前元素和所有未来元素绑定事件。轻松愉快! :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接