簡體   English   中英

HTML5歷史記錄禁用前進按鈕

[英]HTML5 history disabling forward button

我正在使用HTML5 History API編寫單頁javascript應用程序。 應用程序通過Ajax加載內容,並使用屏幕堆棧在內部維護前景屏幕上的狀態信息。

我想使用后退按鈕啟用導航,但我從不想要啟用前進按鈕。

一些快速的信息:

  • 用戶應該只能回頭,永遠不能前進
  • 按瀏覽器后退按鈕可關閉用戶所在的當前頁面屏幕並重新加載上一個屏幕
  • Project僅針對最新版本的Chrome,因此其他瀏覽器實施並不重要
  • 我只使用本機JavaScript和jQuery,我想在沒有History.js的情況下這樣做

當我加載新屏幕時,我運行以下行:

history.pushState(screenData, window.document.title, "#");

我通過jQuery綁定到popstate事件:

$(window).bind("popstate", function(event) {
    if (event.originalEvent.state != null) {
        // Logic that loads the previous screen using my screen stack
    }
}); 

我的應用程序的歷史記錄管理正在運行,但是當我返回時,啟用了前進按鈕。 我需要弄清楚如何從popstate事件中刪除history中的數據。

我可以用replaceState做這個嗎? 我不知道怎么做這個......

不好的部分

要真正禁用轉發按鈕,您必須能夠刪除瀏覽器歷史記錄,這是所有javascript實現都不允許的,因為它允許網站刪除整個歷史記錄,這絕不符合用戶的利益。

好的一部分

這有點棘手,但我想如果你想做自定義歷史記錄它可以工作。 您可以在popstate事件中使用pushState ,使您的實際頁面成為最頂層的歷史記錄條目。 我假設您處理歷史的方式,您的窗口永遠不會卸載。 這允許您自己跟蹤用戶歷史記錄:

var customHistory = [];

使用history.pushState(screenData, window.document.title, "#");推送您加載的每個頁面history.pushState(screenData, window.document.title, "#"); ,就像你之前做的那樣。 只有您將狀態添加到自定義歷史記錄中:

history.pushState(screenData, window.document.title, "#");
customHistory.push({data: screenData, title: window.document.title, location: '#'});

現在,如果你有一個popstate事件,你只需彈出自定義歷史記錄並將其推送到最頂層的條目:

window.onpopstate = function(e) { 
  var lastEntry = customHistory.pop();
  history.pushState(lastEntry.data, lastEntry.title, lastEntry.location);
  // load the last entry
}

或者在jQuery中

$(window).on('popstate', function(e) {
  var lastEntry = customHistory.pop();
  history.pushState(lastEntry.data, lastEntry.title, lastEntry.location);
  // load the last entry
});

接受的答案解決了禁用前進按鈕的問題,但是創建了一個新的煩人問題“導航回頁面”被重復插入到歷史記錄中(如答案評論中所示)。

這是如何解決“diabled forward button”這個問題並避免 “重復”后退按鈕問題。

//setup the popstate EventListener that reacts to browser history events
window.addEventListener("popstate",function(event){
     // In order to remove any "forward"-history (i.e. disable forward 
     // button), this popstate's event history state (having been navigated 
     // back to) must be insert _again_ as a new history state, thereby 
     // making it the new most forwad history state. 
     // This leaves the problem that to have this popstate event's history
     // state to become the new top, it would now be multiple in the history
     //
     // Effectively history would be:
     //  * [states before..] ->
     //  * [popstate's event.state] -> 
     //  * [*newly pushed _duplicate_ of popstate's event.state ]
     // 
     // To remove the annoyance/confusion for the user to have duplicate
     // history states, meaning it has to be clicked at least twice to go 
     // back, we pursue the strategy of marking the current history state
     // as "obsolete", as it has been inserted _again_ as to be the most
     // forward history entry. 
     // 
     // the popstate EventListener will hence have to distinguish 2 cases:
     //
     // case A) "popstate event is _not_ an obsolete duplicate"...
     if( typeof event.state == "object" 
         && event.state.obsolete !== true)
     {
         //...so we _firstly_ mark this state as to from now on "obsolete",
         // which can be done using the history API's replaceState method
         history.replaceState({"obsolete":true},"");
         // and _secondly_ push this state _one_more_time_ to the history
         // which will solve the OP's desired "disable forward button" issue
         history.pushState(event.state,"");
     }

     // case B: there is the other case that the user clicked "back" and
     // encounters one of the duplicate history event entries that are 
     // "obsolete" now.
     if( typeof event.state == "object" 
         && event.state.obsolete === true)
     {
         //...in which case we simply go "back" once more 
         history.back() 
         // by this resolving the issue/problem that the user would
         // be counter-intuively needing to click back multiple times.
         // > we skip over the obsolete duplicates, that have been the
         // the result of necessarily pushing a history state to "disable
         // forward navigation"
     }

},false);

只需使用以下jquery來禁用前進按鈕:

  $( document ).ready( function(){
    history.pushState(null,  document.title, location.href);        
   });

注意:

  • 代碼經過測試並且運行良好而沒有出現任何問題,但是我會激勵開發人員在使用代碼進行生產之前對其進行更多測試
  • 如果在應用程序的任何位置使用HTML5 history.replaceState() ,則下面的代碼現在可以正常工作。

我創建了一個自定義函數以禁用前進按鈕:

這是代碼(不適用於散列路由策略):

  <script>
    (function() {
      // function called after the DOM has loaded
      disableForwardButton();
    })();

    function disableForwardButton() {
      var flag, loop = false;
      window.addEventListener('popstate', function(event) {
        if (flag) {
          if (history.state && history.state.hasOwnProperty('page')) {
            loop = true;
            history.go(-1);
          } else {
            loop = false;
            history.go(-1);
          }
        } else {
          history.pushState({
              page: true
            },
            null,
            null
          );
        }
        flag = loop ? true : !flag;
      });

      window.onclick = function(event) {
        flag = false;
      };
    }
  </script>

正如Redrif用戶在接受的答案的評論中指出的那樣。 問題是你必須雙擊后退按鈕才能導航回到繁瑣且不切實際的頁面。

代碼說明:每次單擊后退按鈕時,都需要創建一個附加的歷史記錄元素,以便您所在的當前頁面指向新創建的歷史記錄頁面。 這樣就沒有頁面要繼續了,因為pushState是最后一個狀態(將它作為數組中的最后一個元素),因此你的前進按鈕將始終被禁用。

之所以必須引入循環變量是因為你可以有一個場景,你回到某個頁面,而pushState代碼會創建最后一個歷史元素,而是再次返回,你選擇再次點擊一些鏈接並再次返回上一頁,現在創建一個額外的歷史元素。 換句話說,你有這樣的事情:

[第1頁,第2頁,第2頁,第2頁]

現在,一旦在page2(索引3元素)上再次單擊后退按鈕,您將再次訪問page2索引1元素,而您不希望這樣。 請記住,您可以擁有一個x page2元素數組,因此引入了循環false變量來解決該特定情況,無論它在數組中有多少page2元素,您都可以從第2頁一直跳到第1頁。

完整的功能描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM