【问题标题】:Popstate event not triggered after pushing twice to history using history.pushState()使用 history.pushState() 将两次推送到历史记录后未触发 Popstate 事件
【发布时间】:2016-08-05 08:43:18
【问题描述】:

我正在开发一个在 iframe 中在页面顶部打开项目的 eshop。我正在使用

history.pushState(stateObj, "page 2", http://localhost:8888/product-category/tyger/vara-tyger/?view=product&item=test-4);

为了让客户复制当前 url 并使用它转到当前页面,并在 iframe 中打开项目。另外,我正在使用

window.addEventListener('popstate', manageHistory);

function manageHistory(event) {
    if (!has_gone_back) {
        var iframeOpen = false;
        has_gone_back = true;
    }
    else {
        var iframeOpen = true;
        has_gone_back = false;
    }
}

为了让客户使用浏览器的后退和前进按钮进行导航(关闭和打开 iframe)。

但是,当打开一个产品(调用一次history.pushState),使用浏览器的后退按钮,打开另一个产品(再次调用history.pushState)并再次返回时,不会调用manageHistory()。客户被带到第一个打开的产品,但如果再次按下,manageHistory() 被调用。

我希望在第二个打开的产品页面上按回时调用manageHistory(),以便添加代码以在按回时将客户重定向到类别的起始页面。

我已经尝试为两个打开的产品添加事件监听器,也只为第一个产品添加事件监听器。任何想法可能是什么问题?

【问题讨论】:

    标签: javascript browser-history event-listener pushstate popstate


    【解决方案1】:

    来自https://developer.mozilla.org/en-US/docs/Web/Events/popstate

    请注意,仅调用 history.pushState() 或 history.replaceState() 不会触发 popstate 事件。 popstate 事件只能通过执行浏览器操作来触发,例如单击后退按钮(或在 JavaScript 中调用 history.back())。

    您可以覆盖popStatereplaceState,但通常更好的做法是创建一个包装器,它设置网址然后触发您的处理程序函数。

    这样的……

    function urlChangeHandler() {
      var url = window.location.href;
    
      // Whatever you want to do...
    }
    
    // Handle initial url:
    urlChangeHandler();
    
    window.addEventListener('popstate', urlChangeHandler);
    
    var urlState = {
      push: function(url) {
        window.history.pushState(null, null, url);
        urlChangeHandler();
      },
      replace: function(url) {
        window.history.replaceState(null, null, url);
        urlChangeHandler();
      }
    }
    

    我的一个项目中有一个类似的文件,它根据#hash 更新数据存储...

    import tree from './state'
    
    
    // No need for react-router for such a simple application.
    
    function hashChangeHandler(commit) {
      return () => {
        const hash = window.location.hash.substr(1);
    
        const cursor = tree.select('activeContactIndex');
        const createCursor = tree.select('createNewContact');
    
        cursor.set(null);
        createCursor.set(false);
    
        (() => {
          if(!hash.length) {
            // Clean up the url (remove the hash if there is nothing after it):
            window.history.replaceState(null, null, window.location.pathname);
            return;
          }
    
          if(hash === 'new') {
            createCursor.set(true);
            return;
          }
    
          const index = parseInt(hash, 10);
          if(!isNaN(index)) {
            cursor.set(index);
          }
        })();
        commit && tree.commit();
      }
    }
    
    // Handle initial url:
    hashChangeHandler(true)();
    
    // Handle manual changes of the hash in the url:
    window.addEventListener('hashchange', hashChangeHandler(true));
    
    function createHash(location) {
      return (location !== null) ? `#${location}` : window.location.pathname;
    }
    
    module.exports = {
      push: (location, commit=true) => {
        window.history.pushState(null, null, createHash(location));
        hashChangeHandler(commit)();
      },
      replace: (location, commit=true) => {
        window.history.replaceState(null, null, createHash(location));
        hashChangeHandler(commit)();
      }
    }
    

    【讨论】:

    • 当我尝试使用你的代码时,我得到了Unexpected token '>'。我正在使用 Wordpress,是否需要添加库或其他内容?
    • 这只是我编写的示例代码。这是我从我的一个项目中复制的第二个代码 sn-p 的编辑版本。它实际上是一个模块,希望您使用webpackbrowserify 之类的东西。此外,还有 ES2015 语法,所以你需要一个转译器,比如 babel。阅读它,了解它的作用,然后在您的应用程序中重新实现它。我会将其重写为香草 javascript。
    猜你喜欢
    • 2012-06-12
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多