【问题标题】:How to avoid calling history.pushState in the popstate event handler?如何避免在 popstate 事件处理程序中调用 history.pushState?
【发布时间】:2015-03-05 17:42:35
【问题描述】:

假设我们有一个<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(); 会强制链接就像用户点击它一样工作,这很好,但不幸的是popstate 事件处理程序不能打电话给history.pushState(在onclick里面)。在 Firefox 中,此代码破坏了前进按钮,这是不可取的。

问题:正确编写对history.pushStatepopstate 事件处理程序的调用的最简单方法是什么,考虑到无论我们做什么,popstate 都必须触发打电话给PrimeFacesGeneratedFunction(stuff)

谢谢!

【问题讨论】:

  • 为什么不能直接在popstate 事件处理程序中调用PrimeFacesGeneratedFunction() 而不是间接调用?
  • 因为不知道生成的函数叫什么名字,也不知道参数。
  • 所以在你的commandLink标签中,你用pushState指定onclick属性,但是当它被翻译成HTML时,除了你提到的之外,PrimeFaces添加了一些额外的js函数来调用onclick在 commandLink 中,我的理解正确吗?
  • 是的,你理解正确。我通过使用不同的 JSF 代码解决了这个问题。

标签: javascript jquery primefaces html5-history


【解决方案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,而是使用&lt;p:remoteCommand&gt;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 事件处理程序引用&lt;p:remoteCommand name&gt; 属性,而不是在原始链接上调用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");
            }
        }
    }
}

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

【讨论】:

  • 酷..很高兴知道这个信息:-)
  • 我想知道我是否可以有一个&lt;p:remoteCommand&gt; 标签并传递一些参数,但这是另一个问题。 :)
猜你喜欢
  • 2020-04-06
  • 2012-06-12
  • 2023-03-09
  • 2017-05-18
  • 2014-08-03
  • 1970-01-01
  • 2012-12-16
  • 2013-01-06
  • 1970-01-01
相关资源
最近更新 更多