3.2 練習

html5 資料夾下,建立一個空的 history 資料夾。並建立 4 個檔案,分別是 a.htmlb.htmlc.htmld.html

內容都是:

<!DOCTYPE html>
<html lang="zh-Hant">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <ul>
      <li><a href="./a.html">A 網頁</a></li>
      <li><a href="./b.html">B 網頁</a></li>
      <li><a href="./c.html">C 網頁</a></li>
      <li><a href="./d.html">D 網頁</a></li>
    </ul>
    
    <!-- 以下標題,a.html 就寫 A 網頁;b.html 就寫 B 網頁。依此類推 -->
    <h1>A 網頁</h1>
  </body>
</html>

確認使用本機端網域的方式開啟。

練習 1:上一頁、下一頁

step1:

瀏覽 http://127.0.0.1:5500/history/a.html 然後點 B 網頁連結,再點擊 C 網頁連結。開啟開發者工具,到 console 的頁籤,執行以下程式:

上一頁:

history.back();
// 或
history.go(-1);

下一頁:

history.forward();
// 或
history.go(1);

相對於當前的頁面,下一頁再下一頁:

history.go(2);

練習 2:瀏覽歷程的新增

瀏覽 http://127.0.0.1:5500/history/a.html 頁面,然後點 B 網頁連結,再點擊 C 網頁連結。開啟開發者工具,執行以下程式:

history.pushState(null, null, "d.html");

再按「上一頁」、「下一頁」觀察看看頁面的變化。

練習 3:瀏覽歷程的更新

瀏覽 http://127.0.0.1:5500/history/a.html 頁面,然後點 B 網頁連結,再點擊 C 網頁連結。開啟開發者工具,執行以下程式:

history.replaceState(null, null, "d.html");

再按「上一頁」、「下一頁」觀察看看頁面的變化。

實際用法

練習 1:中間卡一個首頁

註:Safari 16 版本開始之後,變得不支援。

history 資料夾裡,再建立一個 e.html 檔案,內容如下:

<!DOCTYPE html>
<html lang="zh-Hant">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>

    <h1>E 網頁</h1>
    <script>
      // document.referrer: 可取得是哪個網址連過來。
      // 但從 https 網站 連到 http 網站,以下這行會印出空字串,因為 http 網站較不安全。
      // console.log(document.referrer);
      
      // 以下的 if 判斷:是判斷是否從外部網站進來自己網站
      //console.log(document.referrer); // ""
      //console.log(location.host);     // 127.0.0.1:5500
      if( !(document.referrer).includes(location.host) ){
        alert("從外站進來這頁");

        // 將目前網址先暫存(e.html)
        var current_url = location.href; // e.html

        // 將目前瀏覽歷程的 url 設定為 a.html // referrer → a.html → e.html
        history.replaceState(null, null, "a.html");

        // 新增一個瀏覽歷程,為 current_url
        history.pushState(null, null, current_url);
      }
      
      window.addEventListener("popstate", function(e){
        //console.log("123");
        location.reload();
      });
    </script>
  </body>
</html>

如果是從 外站,點擊某個連結到自己網站的某一頁(非首頁,此例為 e.html 頁面),那麼希望按上一頁的時候,設定回到首頁(此例為假設 a.html)。

實際測試:在 Chrome 瀏覽器,例如已經在 e.html 頁面上,需要在任何空白處有點擊的動作,然後是再按回上一頁,才會回到 a.html 頁面。

練習 2:頁籤的瀏覽歷程

history 資料夾裡,建立 tab.html 檔案,內容如下:

<!DOCTYPE html>
<html lang="zh-Hant" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <style>
      * {
        box-sizing: border-box;
      }
      /* 整個頁籤及內容最外層區塊 */
      div.tab_container{
        
      }
      
      /* 頁籤區塊 */
      div.tab_container div.tab_list_block{
        padding-left: 20px;
        position: relative;
        z-index: 2;
      }
      
      /* 頁籤列表 */
      div.tab_container div.tab_list_block ul.tab_list{
        list-style: none;
        display: inline-block;
        margin: 0;
        padding: 0;
      }
      div.tab_container div.tab_list_block ul.tab_list > li{
        display: inline-block;
      }
      div.tab_container div.tab_list_block ul.tab_list > li > a{
        text-decoration: none;
        display: inline-block;
        border-top: 1px solid #ccc;
        border-right: 1px solid #ccc;
        border-left: 1px solid #ccc;
        
      /*   border-bottom: 1px solid black; */
        padding: 2px 20px;
        border-radius: 5px 5px 0 0;
        cursor: pointer;
        color: #ccc;
      }
      
      /* 畫出底部黑線 */
      
      div.tab_container div.tab_list_block ul.tab_list > li > a.-on{
        border-top: 1px solid black;
        border-right: 1px solid black;
        border-left: 1px solid black;
        border-bottom: 1px solid white;
        color: black;
      }
      
      /* 頁籤內容區塊 */
      div.tab_container div.tab_contents{
        border: 1px solid black;
        position: relative;
        top: -1px;
        
        z-index: 1;
      }
      div.tab_container div.tab_contents div.tab{
        padding: 10px;
        display: none;
      }
      div.tab_container div.tab_contents div.tab.-on{
        display: block;
      }
    </style>
  </head>
  <body>
    <div class="tab_container">

      <div class="tab_list_block">
        <ul class="tab_list">
          <li><a href="#" data-target="tab1" class="tab -on">頁籤一</a></li>
          <li><a href="#" data-target="tab2" class="tab">頁籤二</a></li>
          <li><a href="#" data-target="tab3" class="tab">頁籤三</a></li>
        </ul>
      </div>

      <div class="tab_contents">

        <div class="tab tab1 -on">
          頁籤一的內容<br>
          內容
        </div>

        <div class="tab tab2">
          頁籤二的內容<br>
          <a href="https://tw.yahoo.com">yahoo 網站</a>
        </div>

        <div class="tab tab3">
          頁籤三的內容<br>
          內容
        </div>
      </div>

    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script>

      // 第二步:函式

      $(function(){
        
        // 第三步

        $("a.tab").on("click", function(e){
          e.preventDefault();

          /* 將頁籤列表移除所有 -on,再將指定的加上 -on */
          $(this).closest("ul").find("a.tab").removeClass("-on");
          $(this).addClass("-on");

          /* 找到對應的頁籤內容,加上 -on 來顯示 */
          $("div.tab").removeClass("-on");
          $("div.tab." + $(this).attr("data-target")).addClass("-on");

          // 第一步
          
        });

      });

      // 第二步

    </script>
  </body>
</html>

然後開啟瀏覽器操作看看。

問題點:點擊頁籤,或外部網站,再按上一頁,沒有回到正確的分頁內容。

第一步:點擊頁籤時,加進瀏覽歷程

history.pushState(null, null, "#" + this.getAttribute("data-target"));

第二步:加上自訂函式

function tab_active(){
  let target_tab;
  switch(location.hash){
    case "#tab1":
      target_tab = "tab1";
      break;
    case "#tab2":
      target_tab = "tab2";
      break;
    case "#tab3":
      target_tab = "tab3";
      break;
    default:
      target_tab = "tab1";
  }
  
  var all_a_tab = document.querySelectorAll("a.tab");
  for(let i = 0; i < all_a_tab.length; i++){
    all_a_tab[i].classList.remove("-on");
  }
  document.querySelector("a.tab[data-target=" + target_tab + "]").classList.add("-on");
  
  var all_div = document.querySelectorAll("div.tab");
  for(let i = 0; i < all_div.length; i++){
    all_div[i].classList.remove("-on");
  }
  document.querySelector("div.tab." + target_tab).classList.add("-on");
}

然後在 popstate 事件觸發時,執行 tab_active() 程式,寫法如下:

// 第二步:popstate 事件觸發,執行 tab_active() 函式
window.addEventListener("popstate", function(){
  tab_active();
});

第三步:連到外部網站,再按上一頁時,會觸發 DOMContentLoaded 事件,所以再執行:

tab_active();

以下 CodePen,是將上述的 jQuery 轉成 JS 的語法(註:此例無法在 CodePen 上執行):https://codepen.io/carlos411/pen/dyzEbdj

Last updated