prevent window.onhashchange from executing when hash is set via JavaScript

十年热恋 提交于 2019-12-22 07:05:24

问题


I use the window.onhashchange function to execute code when the User changes the hash of the page:

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

In some functions I also set the hash via JavaScript:

window.location.hash = "#abc";

I want to prevent the onhashchange event from firing when I set the hash via JavaScript.

What I have tried so far:

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;

That didn't work because the event is fired with a delay, so the code will first set the hash, then set "currently_setting_hash" to false and then execute the onhashchange event.

Any ideas how this could be accomplished? Or maybe is there a way to detect if the hash was set by the user or via JavaScript?


回答1:


You could reset the variable from the event handler itself:

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";



回答2:


Since the event is delayed, there is the possibility of events occurring in a different order than you expect (e.g. imagine the user changing the URL by other means either immediately before or after your code does). It is important to make sure that you do not become inconsistent by assuming the event is yours. Therefore I have a suggestion (based on your code and Adam Bubela's):

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;
}

This code will suppress the change handler only if the change is to the value you are expecting. (The assignment inside of onhashchange makes sure that the handler also runs if the hash temporarily goes to another value, which I assume is more correct than the alternative.)

The third helper function canonicalizeHashValue is needed only for precision in case you are specifying a non-canonical value, e.g. changeHash('foo') instead of changeHash('#foo').




回答3:


If you want to use just plain Java Script:

    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;
    }



回答4:


Well, since the event is delayed, if you change hash (for any reason) more than once, then more events will fire in a row. In such case you should increment an integer every time hash is changed.

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;
}


来源:https://stackoverflow.com/questions/13233914/prevent-window-onhashchange-from-executing-when-hash-is-set-via-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!