了解hashchange事件的执行顺序

时间:2015-10-12 17:44:18

标签: javascript jquery

关于此代码段,我有一个问题:

window.location.hash=1;

$(window).on('hashchange', function() {
    alert('hello');
});

上面的脚本应该这样做:

  1. 将位置哈希设置为1
  2. 任何进一步的变化 - > alert('hello')
  3. 这是问题:为什么在第一次执行时第一次调用hashchange?这个脚本不应该只更改哈希而没有任何警报吗?

    如何修复它以使其按照描述工作?

3 个答案:

答案 0 :(得分:3)

首先,你问:

  

为什么在第一次执行时第一次调用hashchange?这个脚本不应该只更改哈希而没有任何警报吗?

要回答这个问题,我们可以delve into the specification。导航到新片段(即设置document.location.hash)时,the specification会经历多个步骤,其中一个步骤是:

  
      
  1. 将历史记录遍历到新条目,并设置异步事件标记。这将滚动到现在文档地址中给出的片段标识符。
  2.   

traversing the history的规范继续说:

  
      
  1. 如果未设置异步事件标志,则同步运行以下步骤。 否则,设置异步事件标志;将任务排队以运行以下子步骤。      
        
    1. 如果状态更改为true,则使用PopStateEvent接口在Document的Window对象上触发名为popstate的受信任事件,并将state属性初始化为state的值。此事件必须冒泡但不可取消,并且没有默认操作。
    2.   
    3. 如果散列更改为true,则使用HashChangeEvent接口在浏览上下文的Window对象中触发名为hashchange 的受信任事件,并将oldURL属性初始化为旧URL并初始化newURL属性到新的URL。此事件必须冒泡但不可取消,并且没有默认操作。
    4.   
  2.   

因此,所有这些结合在一起意味着当您运行代码时,{I}的事件侦听器将在步骤14的子步骤中的代码运行之前添加,并且随后将在设置哈希时触发

  

如何修复它以使其按照描述工作?

要修复此问题,您还可以使用setTimeout(.., 0)

对添加事件监听器进行排队
hashchange

由于您在设置散列后将其添加到队列中,因此在上面的步骤14中排队的任务之后,它将被添加到队列中,因此仅在事件被触发后才添加事件侦听器。

答案 1 :(得分:0)

在代码中使用计数器:

var counter = 0;

$(window).on('hashchange', function() {
    if (counter)
        alert('hello');
    counter++;
});

答案 2 :(得分:0)

在不调用setTimeout的情况下修复它的另一种方法是注册'hashchange'事件,然后设置hash的值。

$(window).on("hashchange",function() 
{
  alert('Invoked due to hash change' + window.location.hash);
});

alert('Hash Updated');
window.location.hash = "1";

小提琴:http://jsfiddle.net/86829ryz/10/