4

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

  1. window.location.hash在初始化时已经针对具有相同 ID 的元素
  2. 单击以元素为目标的锚点
  3. hashchange事件独立于上述触发(例如通过window.historyAPI)

场景 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事件时再次触发。如何过滤掉这些边缘情况?

解决方案后编辑:

烤的答案是关键 - 处理命名空间的 hashchange 事件,然后根据 click 处理程序及其 preventDefault 内部处理的逻辑取消绑定并重新绑定处理程序。我在这里写了完整的插件

4

3 回答 3

5

如果我理解它,您不希望在单击锚标记时触发 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));
}
于 2013-07-30T13:25:17.787 回答
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

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

于 2013-07-29T21:03:10.303 回答
0

如果您要在其上调用 preventDefault ,似乎您可以使用 mousedown 而不是单击。然后大概不会触发 hashchange。

于 2013-07-29T05:52:34.750 回答