【问题标题】:Hashchange event listener listens before event handler is attached to eventHashchange 事件侦听器在事件处理程序附加到事件之前进行侦听
【发布时间】:2015-02-13 12:21:59
【问题描述】:

我有以下代码

console.info('checking if url contains hash');
if (!location.hash) {
  console.warn('if-block replacing hash to empty!');
  location.href = '#';

  // Running route() to trigger Router.otherwise()
  console.info('running route() from if-block(hash doesn\'t exist)');
  route(location.hash.slice(1));
} else {
  // URL contains a hash. Running Router.when() to load template
  console.info('running route() from else-block(hash already present in url)');
  route(location.hash.slice(1));
}

// Bind hashchange-event to window-object... duh
console.info('binding hashchange event');
$(window).on('hashchange', function () {
  console.info('running route() from hashchange');
  route(location.hash.slice(1));
});

显然,事件侦听器附加在 else-if 块之后。我的控制台输出验证了这一点

2015-02-13 12:51:14.281 main.js:69 checking if url contains hash
2015-02-13 12:51:14.284 main.js:71 if-block replacing hash to empty!
2015-02-13 12:51:14.290 main.js:75 running route() from if-block(hash doesn\'t exist)
2015-02-13 12:51:16.677 main.js:84 binding hashchange event
2015-02-13 12:51:16.678 main.js:86 running route() from hashchange

看起来事件侦听器以某种方式获取了之前触发的 hashchange 事件。
这仅在 url 为 example.com 而不是 example.com/# 时发生。如果您进入网站时,网址中缺少//#,则会触发此现象。

编辑:我遇到的问题是hashchange 事件侦听器在它甚至侦听哈希更改之前就触发了。我想知道这是否正常。

另一个编辑: 一个更清晰的示例表明,当我第一次运行 getEventListeners(window) 时,没有侦听器附加到 hashchange 事件。尽管如此,当我添加事件侦听器时,它会拾取先前触发的hashchange

我在这里遗漏了什么还是发生了什么?
有没有办法绕过这个?

【问题讨论】:

  • 绕过什么?显示的内容中没有任何内容表明事件过早触发。请更详细地解释问题。完全不清楚预期是什么
  • @charlietfl 我在我的 OP 中添加了说明
  • 是什么让你说它过早触发?您的编辑是控制台日志中显示的内容不支持的语句复制问题的演示会有所帮助
  • @charlietfl 控制台日志指出,在第 69 行,我的 if-else 块开始运行并将哈希添加到 url,因此触发了 hashchange 事件。但我尚未将事件侦听器附加到 hashchange,如控制台日志的第 84 行所示。
  • 那你需要显示更多代码,显示代码的方式日志是对的

标签: javascript jquery hashchange


【解决方案1】:

让我们将您的代码简化为

location.hash = 'foobar';
window.onhashchange = function() {
  document.body.innerHTML = 'You should not see me. But you do :(';
};

要解决问题,可以使用setTimeout来延迟添加事件处理程序:

location.hash = 'foobar';
setTimeout(function(){ // Delayed code
  window.onhashchange = function() {
    document.body.innerHTML = 'You should not see me. And you do not :)';
  };
}, 0);

【讨论】:

  • 我知道我可以将其用作解决方法。但为什么首先会出现这个问题?
  • @rymdsylt 不确定,可能是异步更新的。您可以在 URL spec 中看到 hash 设置器步骤,但我对该规范的了解不够多,无法看到它发生在哪里。
  • 好吧,既然您的示例帮助我解决了这个问题,我将其标记为已解决。谢谢老兄!
猜你喜欢
  • 1970-01-01
  • 2017-12-16
  • 2013-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
相关资源
最近更新 更多