如何避免在popstate事件处理程序中调用history.pushState?

时间:2015-03-05 17:42:35

标签: javascript jquery primefaces html5-history

我们假设我们有<p:commandLink action="…" onclick="history.pushState(…)">对页面状态进行重要更改。 Primefaces 5.1生成此HTML:

<a id="link1" href="#"
    onclick="history.pushState( {currentStateKeyWord: 'state1'},'','state1');
             PrimeFacesGeneratedFunction(stuff);">Click me for state 1</a>
<a id="link2" href="#"
    onclick="history.pushState( {currentStateKeyWord: 'state2'},'','state2');
             PrimeFacesGeneratedFunction(stuff);">Click me for state 2</a>

popstate事件处理程序中,我们必须根据在pushState中作为第一个参数推送的对象来恢复状态。使用JQuery:

jQuery(document).ready(function(jQuery) {
    jQuery(window).bind('popstate', function(event) {
        if ((event.originalEvent.state!==null)
             && (event.originalEvent.state.currentStateKeyWord!==undefined)) {
            switch (event.originalEvent.state.currentStateKeyWord) {
                case 'state1':
                    jQuery("#link1").click();
                    break;
                case 'state2':
                    jQuery("#link2").click();
                    break;
                 default:
                    console.error("Unknown state");
            }
        }
    }
}

为什么这不起作用:使用jQuery("#link1").click();强制链接工作就像用户点击它一样,这样会很好,但不幸的是{{1}事件处理程序不能调用popstate(在history.pushState内)。在Firefox中,此代码会中断前进按钮,这是不可取的。

问题:正确编写对onclickhistory.pushState事件处理程序的调用的最简单方法是,考虑到我们所做的一切,{ {1}}必须触发对popstate的调用?

谢谢!

1 个答案:

答案 0 :(得分:1)

昨天我认为解决方案将在客户端,并且像往常一样,我今天早上醒来时的想法完全不同。

我原来的JSF代码是:

<p:commandLink action="#{associateBean.setState('state1')}" 
       onclick="history.pushState('{currentStateKeyWord: 'state1'}','','state1')"
       update="somePanel"/>

<p:commandLink action="#{associateBean.setState('state2')}" 
       onclick="history.pushState('{currentStateKeyWord: 'state2'}','','state2')"
       update="somePanel"/>

如上所述,问题是Primefaces生成一个HTML锚点(a)并使用onclick属性来调用我自己的onclick代码(history.pushState)和一些与action属性(PrimefacesGeneratedFunction('stuff'))的内容相关的其他函数。

解决方案不是要调整JavaScript,而是使用<p:remoteCommand>action内容移出commandLink

新的JSF代码是:

<p:remoteCommand name="setState1"
     actionListener="#{associateBean.setState('state1')}"  
     update="somePanel"/>
<p:commandLink onclick="setState1();
     history.pushState('{currentStateKeyWord: 'state1'}','','state1')"/>

<p:remoteCommand name="setState2"
    actionListener="#{associateBean.setState('state2')}"
    update="somePanel"/>
<p:commandLink onclick="setState2();
    history.pushState('{currentStateKeyWord: 'state2'}','','state2')"/>

现在,popstate事件处理程序引用了<p:remoteCommand name>属性,而不是在原始链接上调用click()

jQuery(document).ready(function(jQuery) {
    jQuery(window).bind('popstate', function(event) {
        if ((event.originalEvent.state!==null)
             && (event.originalEvent.state.currentStateKeyWord!==undefined))     {
            switch (event.originalEvent.state.currentStateKeyWord) {
                case 'state1':
                    setState1();
                    break;
                case 'state2':
                    setState2();
                    break;
                 default:
                    console.error("Unknown state");
            }
        }
    }
}

希望这会对某人有所帮助。