7

当用户更改页面的哈希时,我使用该window.onhashchange函数执行代码:

window.onhashchange = function() { /* do something */ };

在某些函数中,我还通过 JavaScript 设置哈希:

window.location.hash = "#abc";

当我通过 JavaScript 设置哈希时,我想防止onhashchange事件触发。

到目前为止我已经尝试过:

var currently_setting_hash = false;

window.onhashchange = function() {
  if (currently_setting_hash)
    return;
 //...
}

currently_setting_hash = true;
window.location.hash = "#abc";
currently_setting_hash = false;

这不起作用,因为事件被延迟触发,所以代码将首先设置哈希,然后设置currently_setting_hash为 false,然后执行onhashchange事件。

任何想法如何实现?或者也许有办法检测哈希是由用户设置还是通过 JavaScript 设置的?

4

5 回答 5

10

您可以从事件处理程序本身重置变量:

var currently_setting_hash = false;

$(window).on("hashchange", function() {
    if (currently_setting_hash) {
        currently_setting_hash = false;
        return;
    }

    currently_setting_hash = false;
    //...
});

currently_setting_hash = true;
window.location.hash = "#abc";
于 2012-11-05T14:20:07.487 回答
4

由于事件被延迟,事件发生的顺序可能与您预期的不同(例如,想象用户在您的代码之前或之后立即通过其他方式更改 URL)。重要的是要确保您不会因为假设事件是您的而变得不一致。因此,我有一个建议(基于您的代码和 Adam Bubela 的):

var expectedHash;

window.onhashchange = function () {
    if (window.location.hash === expectedHash) {
        return;
    }
    expectedHash = window.location.hash;
    // ... do actual reaction to change here ...
}

function changeHash(hash) {
    hash = canonicalizeHashValue(hash);
    expectedHash = hash;
    window.location.hash = hash;
}

// Helper - return the version of the URL that the browser is expected to
// so that the equality test is accurate.
function canonicalizeHashValue(value) {
    // Borrowing an A element's ability to resolve/parse URLs.
    var tmp = document.createElement('a');
    tmp.href = "";
    tmp.hash = value;
    return tmp.hash;
}

仅当更改为您期望的值时,此代码才会禁止更改处理程序。(如果哈希暂时变为另一个值,则内部的分配onhashchange确保处理程序也运行,我认为这比替代方案更正确。)

第三个辅助函数canonicalizeHashValue仅在您指定非规范值(例如,changeHash('foo')而不是changeHash('#foo').

于 2012-11-05T14:40:21.363 回答
3

如果您只想使用普通的 Java 脚本:

    var currently_setting_hash = false;

    window.onhashchange = function() {
        if (currently_setting_hash){
            currently_setting_hash = false;
            return;
        //...
        }
        alert('outside the script');
    }
    function changeHash(hash){
        currently_setting_hash = true;
        window.location.hash = hash;
    }
于 2012-11-05T14:32:49.987 回答
0

好吧,由于事件被延迟,如果您多次更改哈希(出于任何原因),那么将连续触发更多事件。在这种情况下,您应该在每次更改散列时增加一个整数。

var setting_hash = 0;

window.onhashchange = function() {
    if (setting_hash){
        setting_hash--;
        return;
    }
    //code here
}
function changeHash(hash) {//hash without '#'
    if (hash!=window.location.hash.substr(1)) {
      setting_hash++;
    }
    window.location.hash = hash;
}
于 2016-03-29T14:38:02.750 回答
0

现在您可以使用 History.replaceState() 方法。它在不触发“onhashchange”的情况下替换哈希。

window.onhashchange = function() { /* do something */ };

// ... 

history.replaceState(undefined,undefined,'#1234');  // This will replace the hash without triggering 'onhashchage'.
于 2021-05-25T17:20:50.003 回答