Javascript JSF/PrimeFaces ajax更新破坏了jQuery事件侦听器函数绑定

Javascript JSF/PrimeFaces ajax更新破坏了jQuery事件侦听器函数绑定,javascript,jquery,ajax,jsf-2,primefaces,Javascript,Jquery,Ajax,Jsf 2,Primefaces,我正在使用jQuery为HTML中的每个输入注册change事件侦听器,如下所示: <h:head> <script type="text/javascript"> //<![CDATA[ $(document).ready(function(){ $(':input').each(function() { $(this).change(function() {

我正在使用jQuery为HTML中的每个
输入注册
change
事件侦听器,如下所示:

<h:head>
    <script type="text/javascript">
        //<![CDATA[
        $(document).ready(function(){
            $(':input').each(function() {
                $(this).change(function() {
                    console.log('From docReady: ' + this.id);
                });
            });
        });

        function changeHandler() {
            console.log("from changeHandler");
        }
        //]]>
    </script>
</h:head>
<h:body>
    <h:form id="topForm">
        <p:commandButton id="myButton" value="update"
                         action="#{testBean.submit}"
                         partialSubmit="true" process=":myForm:panel"
                         update=":myForm:panel" />
    </h:form>
    <h:form id="myForm">
        <p:panel id="panel">
            <p:inputTextarea id="myTextarea"
                             value="#{testBean.val}"
                             onchange="changeHandler();"/>
        </p:panel>
    </h:form>
</h:body>

//
如果用户更改
myTextarea
的内容,则会触发两个
change
事件。但是,在按下部分更新
myTextarea
的更新按钮后,只有changeHandler随后触发。
$(document).ready()
中绑定的事件不再触发


这是相关的和/或预期的行为吗?如果是,那么如何确保触发第二个事件而不再次运行document ready脚本。

至于问题的原因,ajax请求将使用ajax响应中的新HTML元素更新HTML DOM树。显然,这些新的HTML元素没有附加jQuery事件处理程序函数。但是,
$(document).ready()
不会在ajax请求上重新执行。您需要手动重新执行它

这可以通过多种方式实现。最简单的方法是使用
$(文档).on(事件、选择器、函数)
而不是
$(选择器).on(事件、函数)
。这与文档相关,并且当在与给定的
选择器
匹配的元素上触发给定的
事件名
时,始终会调用给定的
函数ref
。因此,您永远不需要通过JSF方式显式地重新执行函数

$(document).on("change", ":input", function() {
    console.log("From change event on any input: " + this.id);
});

另一种方法是在完成ajax请求后自己显式地重新执行函数。这是在
ready
/
load
事件期间(例如,直接应用某些特定于插件的行为/外观,如日期选择器)您真正有兴趣立即执行函数的唯一方法。首先,您需要将
$(document).ready()作业重构为可重用函数,如下所示:

$(document).ready(function(){
    applyChangeHandler();
});

function applyChangeHandler() {
    $(":input").on("change", function() {
        console.log("From applyChangeHandler: " + this.id);
    });
}
(请注意,我删除并简化了完全不必要的
$.each()
方法)

然后,选择以下方法之一在ajax请求完成时重新执行它:

<p:outputPanel autoUpdate="true">
    <h:outputScript id="applyChangeHandler">
        applyChangeHandler();
    </h:outputScript>
</p:outputPanel>
  • 使用PrimeFaces命令按钮的
    oncomplete
    属性:

    oncomplete="applyChangeHandler()"
    
  • 使用
    而不是
    $(document).ready()

  • 使用
    在每次ajax请求时自动更新:

    <p:outputPanel autoUpdate="true">
        <h:outputScript id="applyChangeHandler">
            applyChangeHandler();
        </h:outputScript>
    </p:outputPanel>
    

  • 至于问题的原因,ajax请求将使用ajax响应中的新HTML元素更新HTMLDOM树。显然,这些新的HTML元素没有附加jQuery事件处理程序函数。但是,
    $(document).ready()
    不会在ajax请求上重新执行。您需要手动重新执行它

    这可以通过多种方式实现。最简单的方法是使用
    $(文档).on(事件、选择器、函数)
    而不是
    $(选择器).on(事件、函数)
    。这与文档相关,并且当在与给定的
    选择器
    匹配的元素上触发给定的
    事件名
    时,始终会调用给定的
    函数ref
    。因此,您永远不需要通过JSF方式显式地重新执行函数

    $(document).on("change", ":input", function() {
        console.log("From change event on any input: " + this.id);
    });
    

    另一种方法是在完成ajax请求后自己显式地重新执行函数。这是在
    ready
    /
    load
    事件期间(例如,直接应用某些特定于插件的行为/外观,如日期选择器)您真正有兴趣立即执行函数的唯一方法。首先,您需要将
    $(document).ready()作业重构为可重用函数,如下所示:

    $(document).ready(function(){
        applyChangeHandler();
    });
    
    function applyChangeHandler() {
        $(":input").on("change", function() {
            console.log("From applyChangeHandler: " + this.id);
        });
    }
    
    (请注意,我删除并简化了完全不必要的
    $.each()
    方法)

    然后,选择以下方法之一在ajax请求完成时重新执行它:

    <p:outputPanel autoUpdate="true">
        <h:outputScript id="applyChangeHandler">
            applyChangeHandler();
        </h:outputScript>
    </p:outputPanel>
    
  • 使用PrimeFaces命令按钮的
    oncomplete
    属性:

    oncomplete="applyChangeHandler()"
    
  • 使用
    而不是
    $(document).ready()

  • 使用
    在每次ajax请求时自动更新:

    <p:outputPanel autoUpdate="true">
        <h:outputScript id="applyChangeHandler">
            applyChangeHandler();
        </h:outputScript>
    </p:outputPanel>
    

  • 或者您可以使用,这是专门为解决此类问题而设计的技术。@Anthony:这仅适用于通过“普通jQuery”执行的ajax请求和通过“普通jQuery”附加的HTML DOM元素因为它有自己的内部事件监听器。我所有的经验告诉我,这两种说法都不正确。@BalusC。谢谢你的发帖。第三种选择似乎适合我的用例。我计划将该代码块放在facelet模板中。对于第三种方法,我删除了$(document).ready(function(){}否则处理程序在初始页面加载时会注册两次,然后手动将可自动更新的p:outputPanel放在正文的末尾。如果我最终发现自己实现了Omnifaces已经提供的功能,我肯定会尝试一下。:@BalusC。有没有办法只在ajax响应之后在新添加的元素上执行脚本?否则,处理程序会一次又一次地绑定到元素。或者您可以使用,这是专门为解决此类问题而设计的技术。@Anthony:这只适用于通过“普通jQuery”执行的ajax请求和通过“普通jQuery”附加的HTML DOM元素因为它有自己的内部事件监听器。我所有的经验告诉我,这两种说法都不正确。@BalusC。谢谢你的发帖。第三种选择似乎适合我的用例。我计划将该代码块放在facelet模板中。对于第三种方法,我删除了$(document).ready(function(){}),否则在初始页面加载时会注册两次处理程序,然后手动将可自动更新的p:outputPanel放在正文的末尾。如果我最终发现自己实现了Omnifaces已经提供的功能,请定义