Pre*_*eli 5 javascript jquery predicate javascript-events fragment-identifier
当用户更改页面的哈希值时,我使用window.onhashchange函数执行代码:
window.onhashchange = function() { /* do something */ };
Run Code Online (Sandbox Code Playgroud)
在某些函数中,我还通过JavaScript设置哈希:
window.location.hash = "#abc";
Run Code Online (Sandbox Code Playgroud)
我想通过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;
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为事件被延迟触发,因此代码将首先设置哈希值,然后将"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";
Run Code Online (Sandbox Code Playgroud)
由于事件被延迟,因此事件发生的顺序可能与您预期的不同(例如,想象用户在代码执行之前或之后通过其他方式更改 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;
}
Run Code Online (Sandbox Code Playgroud)
仅当更改为您期望的值时,此代码才会抑制更改处理程序。(内部的赋值onhashchange确保如果哈希暂时转到另一个值,处理程序也会运行,我认为这比替代方案更正确。)
第三个辅助函数canonicalizeHashValue仅在您指定非规范值(例如changeHash('foo')而不是 )的情况下才需要精度changeHash('#foo')。