仅捕获不是由锚点单击引起的hashchange事件



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

  1. window.location.hash在初始化时已经将相同ID的元素作为目标
  2. 单击以元素为目标的锚点
  3. hashchange事件与上述事件无关(例如通过window.history API)

场景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事件时,它将再次被触发。如何过滤掉这些边缘案例?

解析后编辑:

baked的答案掌握了关键——处理一个名称空间的hashchange事件,然后根据click处理程序内部处理的逻辑及其preventDefault来解除绑定和重新绑定处理程序。我在这里写了完整的插件。

如果我理解的话,你不希望在点击锚标记时触发hashchange事件。然后,您可以使用名称空间事件设置逻辑:

演示

$('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));
}

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

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

这修复了级联问题,无论是什么调用了更改。

如果要调用preventDefault,似乎可以使用mousedown而不是单击。那么可能不会触发hashchange。

相关内容

  • 没有找到相关文章

最新更新