防止 window.onhashchange 在通过 JavaScript 设置哈希时执行



当用户更改页面的哈希时,我使用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 设置的?

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

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

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

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').

如果你想只使用普通的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;
}

现在你可以使用 History.replaceState() 方法。它替换哈希而不触发"onhashchange"。

window.onhashchange = function() { /* do something */ };
// ... 
history.replaceState(undefined,undefined,'#1234');  // This will replace the hash without triggering 'onhashchage'.

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

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

相关内容

  • 没有找到相关文章

最新更新