4

設定我使用window.onhashchange功能,當用戶改變頁面的散列來執行代碼執行:防止window.onhashchange從當散列通過JavaScript

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

在一些功能我還設置散列通過JavaScript:

window.location.hash = "#abc"; 

我想防止onhashchange事件發射時,我通過JavaScript設置散列。

我迄今爲止嘗試:

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設置?

回答

7

您可以在變量從事件處理程序本身復位:

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

我喜歡這個主意 - 馬上就會測試它 – Preli

+0

它的工作原理。你是我的英雄! – Preli

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

由於該事件被延遲,存在的可能性事件的發生順序與預期不同(例如,想象用戶在代碼執行之前或之後通過其他方式更改URL)。通過假設事件是你的事情來確保你不會變得不一致是很重要的。因此,我有一個建議(根據您的代碼和亞當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')

+0

'window.location.hash'包含前導「#」,但'expectedHash'變量沒有,所以不應該'expectedHash'設置爲'expectedHash =「#」+ hash'? – primehalo

+0

@primehalo:你爲什麼認爲'expectedHash'變量不包含'#'? –

+0

當設置'window.location.hash'時,不需要包含散列符號(w3schools實際上表示不應該包含它),所以最好檢查它,如果它不存在,則將其前置。 – primehalo

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