【问题标题】:stop firing popstate on hashchange停止在 hashchange 上触发 popstate
【发布时间】:2014-10-27 08:52:40
【问题描述】:

我正在使用 History API 并使用推送和弹出状态。我想阻止 popstate 事件在我只将哈希附加到 URL 的某些情况下触发。例如,在某些情况下,单击锚点会将 # 附加到 URL 并立即触发 popstate)我想避免将 ##somehasvalue 附加到 URL 并阻止 popstate 触发的所有情况。我正在使用查询参数维护 URL,并且我没有任何需要在 URL 中使用# 触发 popstate 事件的情况。

这是我的代码。

if (supportsHistoryApi()) {

    window.onpopstate = function (event) {
    var d = event.state || {state_param1: param1, state_param2: param2};                       
    var pathName = window.location.pathname,
        params   = window.location.search;

    loadData(event, pathName + params, d.state_param1, d.state_param2);

}

【问题讨论】:

    标签: javascript html5-history


    【解决方案1】:

    据我发现,不幸的是,您无法阻止 popstate 触发。

    您可以做的是检查event.state 对象。这将在哈希更改时为空。 所以我建议添加一个

    if(event.state === null) {
       event.preventDefault();
       return false;
    }
    

    一开始就发送给您的 popstate 事件处理程序。 我认为这是防止在哈希更改时触发您身边的 popstate 处理代码的最佳方法,但我很想知道是否有其他解决方案。

    【讨论】:

    • 这在您返回到您打开的第一页时不起作用。因为那时state也是null,但仍然没有hashchange
    • @HugoDelsing,也许在页面加载时总是replaceState
    • 顺便说一句,popState 事件是not cancelable,所以preventDefault-ing 它什么都不做。在页面加载时检查 null 并结合调用 replaceState 似乎工作正常。
    【解决方案2】:

    如果有人仍然需要这个:

    var is_hashed = false;
    
    $(window).on('hashchange', function() {
        is_hashed = true;
    });
    
    window.addEventListener('popstate', function(e){
        // if hashchange
        if (is_hashed) {
            e.preventDefault();
            // reset
            is_hashed = false;
            return false;
        }
    
        // Your code to handle popstate here
        ..................
    });
    

    【讨论】:

    • 我无法让它工作。使用 Chrome 85。popstate 事件发生在 hashchange 之前
    【解决方案3】:

    这很简单。

    为了防止popstate 事件在您单击带有散列的链接后触发,您必须消除单击链接的后果 - 即在浏览器地址栏中添加散列。

    基本上你必须为click事件创建处理程序,检查点击是否在你想要防止哈希出现在URL中的元素上,并通过在处理程序中调用event.preventDefault();来防止哈希出现。

    下面是代码示例:

    /**
     * This your existing `onpopstate` handler.
     */
    window.onpopstate = function(e) {
        // You could want to prevent defaut behaviour for `popstate` event too.
        // e.preventDefault(); 
        // Your logic here to do things. 
    
        // The following reload is just an example of what you could want to make
        // in this event handler.
        window.location.reload();
    };
    
    /**
     * This is the `click` event handler that conditionally prevents the default
     * click behaviour.
     */
    document.addEventListener('click', function(e) {
        // Here you check if the clicked element is that special link of yours.
        if (e.target.tagName === "A" && e.target.hash.indexOf('#the-link-i-want-make-discernable') > -1) {
            // The 'e.preventDefault()' is what prevent the hash to be added to
            // the URL and therefore prevents your 'popstate' handler to fire.
            e.preventDefault();
            processMySpecialLink(e, e.target);
        }
    
    });
    
    /**
     * Just an example of the link click processor in case you want making something
     * more on the link click (e.g. smooth scroll to the hash).
     */
    function processMySpecialLink(e, target) {
        // Make things here you want at user clicking your discernable link.
    }
    

    这是匹配的 HTML 标记:

    <!-- Somewhere in the markup -->
    <span id="the-link-i-want-make-discernable"></span>
    <!-- Some markup -->
    <a href="#the-link-i-want-make-discernable">My Special Link</a>
    <!-- Another markup -->
    <a href="#just-common-link">Any other link</a>
    

    这一切都做了上面描述的事情:防止特殊哈希链接的默认行为。作为副作用,它不会触发 popstate 事件,因为对于单击 #the-link-i-want-make-discernable 哈希链接的特殊情况,不会向 URL 添加哈希。

    【讨论】:

      【解决方案4】:

      我有办法!

      • 当调用 popstate 事件时,检查路径名是否已更改,或者只是哈希更改。在下面观看它对我的作用:
              window.pop_old = document.location.pathname;
              window.pop_new = '';
              window.onpopstate = function (event) {
      
                  window.pop_new = document.location.pathname;
      
                  if(pop_new != pop_old){
      
                      //diferent path: not just the hash has changed
      
                  } else {
      
                      //same path: just diferent hash
      
                  }
      
                  window.pop_old = pop_new; //save for the next interaction
      
              };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-18
        • 2021-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-12
        相关资源
        最近更新 更多