仅捕获不是由锚点击产生的hashchange事件

时间:2013-07-03 15:17:48

标签: javascript jquery dom hashchange

我正在尝试使用Javascript来模拟CSS :target伪类,以便捕获导致页面上的元素被定位的所有事件。我已经确定了3个触发事件:

  1. window.location.hash已经在初始化时定位了相同ID的元素
  2. 点击定位该元素的锚点
  3. hashchange事件独立于上述情况被触发(例如通过window.history API)
  4. 场景2作为一个独特的案例非常重要,因为我想要调用click事件的preventDefault。此方案的简化代码如下:

    $('body').on('click', 'a[href*=#]', function filterTarget(clickEvent){
        $(this.hash).trigger('target', [clickEvent]);
    });
    

    尝试实施方案3时出现问题:

    $(window).on('hashchange', function filterTarget(hashChangeEvent){
        $(this.hash).trigger('target', [hashChangeEvent]);
    });
    

    如果target处理程序没有取消方案2的本机行为,则当本机行为导致生成的hashchange事件时,它将再次被触发。如何过滤掉这些边缘情况?

    POST-SOLUTION EDIT:

    烘焙的答案持有密钥 - 处理命名空间的hashchange事件,然后根据click处理程序及其preventDefault中处理的逻辑解除绑定并重新绑定处理程序。 I wrote up the full plugin here

3 个答案:

答案 0 :(得分:5)

如果我理解,如果单击一个锚标记,则不希望触发hashchange事件。然后,您可以使用命名空间事件设置逻辑:

DEMO

$('body').on('click', 'a[href*=#]', function (clickEvent) {
    filterTarget(clickEvent,this);  
    $(window).off('hashchange.filter').on('hashchange.tmp', function () {
          $(this).off('hashchange.tmp').on('hashchange.filter', filterTarget);
    });
});
$(window).on('hashchange.filter', filterTarget);

function filterTarget(event,elem) {
    $(elem?elem.hash:window.location.hash).trigger('target', [event]);
    //you could filter depending event.type
    alert(event.type + '::'+ (elem?elem.hash:window.location.hash));
}

答案 1 :(得分:1)

如果单击仍然使用片段设置哈希,只需在哈希更改事件中丢弃重复项:

onhashchange=function(e){
  if(e.newURL == e.oldURL ){return; }
 //do your normal hashchange event stuff below:

};

参考:https://developer.mozilla.org/en-US/docs/Web/API/window.onhashchange

这解决了级联问题,无论调用什么改变。

答案 2 :(得分:0)

似乎你可以使用mousedown而不是click,如果你打算在它上面调用preventDefault。然后可能不会触发哈希转换。