一篇文章圖文並茂地帶你輕松實踐 HTML5 history api


HTML5 history api

前言

由於筆者在網絡上沒有找到比較好的關於 history api 的實踐案例,有的案例過於雜亂,沒有重點,有些案例只是告訴讀者 api 是什么,卻沒告訴怎么用,本文章從零開始帶讀者實踐 history api ,建議和筆者一起寫一遍。

效果

注意 url 變化,另外用到了 虎褲里老師 和 狼大老師 的圖,侵權馬上刪。

流程

  1. html 部分

    需要引入 jquery

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./index.css" />
    <script src="./jquery.js"></script>
    <script src="./index.js"></script>
    <title>history html5</title>
  </head>
  <body>
    <div class="row">
      <button data-id="1" data-name="tiger" class="btn">來一只虎虎</button>
      <button data-id="0" data-name="cow" class="btn">來一只牛牛</button>
    </div>
    <div class="row">
      <img class="image" />
    </div>
  </body>
</html>
  1. css 部分
.row {
  display: flex;
  justify-content: space-around;
}

.image {
  width: 25%;
  height: 25%;
  padding: 20px;
  cursor: pointer;
}
  1. 等待頁面 dom 加載完畢再執行 JS
window.onload = () => {
 	// ...   
}
  1. 獲取 btn 添加事件

    獲取請求所需的 id 以及界面需要展示的 url 路徑

  const btns = document.querySelectorAll(".btn");
  btns.forEach(btn => {
    const dataId = btn.getAttribute("data-id");		// 請求 id
    const dataName = btn.getAttribute("data-name");	// 頁面 url 路徑
      
    btn.addEventListener("click", () => {
      // ...
    });
  });
  1. 模擬網絡請求

    接上方的代碼,這里的話我寫了一份模擬數據

{
  "images": [
    "./images/牛牛.jpg",
    "./images/虎虎.jpg"
  ]
}

​ 並在對應文件夾下存放了圖片,接下來進行 ajax 網絡請求

btn.addEventListener("click", () => {
      $.ajax({
        url: "./mock/mock.json",
        success: (res) => {
          const { images } = res;
          const state = images[dataId];
          displayContent(state);					// 接下來會提到這個函數
          history.pushState(state, null, dataName);	  // 接下來會提到這個函數
        },
      });
    });

​ 這里的話,一般來說是傳入 id 給服務端返回一個圖片的 url 由於為了實現簡單,全部返回后,根據先前從 dom 屬性上獲得的 dataId 獲取圖片的 url

  1. 根據獲得的 url 進行展示
const image = document.querySelector(".image"); 
const displayContent = (src) => {
    image.setAttribute("src", src);
 };
  1. 頁面變化后,利用 html5 history api 進行修改頁面地址,並傳入 state
history.pushState(state, null, dataName);

其中第一個參數后面有個監聽事件會用到,而第二個參數代表標題,沒必要傳,第三個參數是路徑。

如果當前路徑是 /history 則如果傳入的路徑是 cow 則會變成 /history/cow

經過上面的幾個步驟,已經成功完成了利用按鈕切換界面的時候,展示不同的圖片信息。

這個時候,如果點擊返回或者頁面的前進按鈕,跳轉到上一頁或下一頁,是無法顯示網頁信息的。

  1. 前進后退顯示網頁信息
window.addEventListener("popstate", (e) => {
    const { state } = e;
    if (state) displayContent(state);
});

這里的 state 就是前面 pushState 傳的 state,可以根據這個 state 渲染當前界面,這就保證了在前進后退的時候渲染對應的圖像。

這個時候當我們點擊前進和后退的時候,基本是已經可以展示對應的界面的,這樣非常好,但是仍然有個問題,當后退到第一個界面的時候,沒有數據

  1. 替換第一個界面的數據
 history.replaceState("./images/虎虎.jpg", null, location.href);
 image.setAttribute("src", "./images/虎虎.jpg");

這里的話,把第一個界面的數據補充上,其實一般都是經過網絡請求的,這里省略了。現在還存在一個問題,如果跳到某個界面后,刷新,可能會出現獲取不到資源的情況。

這很正常,例如我們在 /history 下有一個 index.html 文件,那么訪問 /history 是可以直接訪問到這個文件的,但是當我們通過上述方法跳轉路由的時候 /history/cow 並不存在 index.html 文件,這意味刷新界面后獲取不到對應的資源了,這個時候上線后還需要 nginx 的輔助配置

  1. 通過 nginxurl rewrite 配置,使得總是命中 history/

總結

不知道大家有沒有用過之前的 vue router 里面如果開啟了 mode: history 的話,最后還要通過 nginx 進行輔助配置,可能就是這個原理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM