監聽瀏覽器更新URL引數,實現偽SPA單頁面應用

bbliang發表於2024-05-30

在老的jqury專案中通常實現SPA一般都採用hash值變化來進行監聽,但是有的專案中我們也想採用改變URL引數來進行監聽,一般我們使用window.history.pushState方法來改變url引數;

為了在使用 window.history.pushStatewindow.history.replaceState 後能夠檢測到瀏覽器的後退按鈕操作,可以透過監聽 popstate 事件來處理瀏覽器導航歷史變化。popstate 事件在使用者點選瀏覽器的後退或前進按鈕時觸發。

說明:
1、監聽瀏覽器地址URL的引數變化;
2、點選瀏覽器前進和後退按鈕的時候也可觸發監聽事件;

下面是示例程式碼:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button onclick="changeUrl()">改變URL引數</button>

    <script>
      /**
       * 改變url引數
       * 隨便找個簡單的例子2個引數p1和p2
       * */
      function changeUrl() {
        let random = Math.floor(Math.random() * 100);
        let newP = `p1=${random}&p2=${random * 2}`;
        updateUrlWithNewParams(newP);
      }

      // 註冊修改 pushState 和 replaceState 以觸發自定義事件
      (function (history) {
        const pushState = history.pushState;
        const replaceState = history.replaceState;

        history.pushState = function (state, title, url) {
          const result = pushState.apply(history, arguments);
          const urlChangeEvent = new Event(urlChangeEventType);
          window.dispatchEvent(urlChangeEvent);
          return result;
        };

        history.replaceState = function (state, title, url) {
          const result = replaceState.apply(history, arguments);
          const urlChangeEvent = new Event(urlChangeEventType);
          window.dispatchEvent(urlChangeEvent);
          return result;
        };
      })(window.history);
      // 自定義事件型別
      const urlChangeEventType = "urlChange";
      // 監聽 popstate 事件以處理瀏覽器後退和前進操作
      window.addEventListener("popstate", function (event) {
        const urlChangeEvent = new Event(urlChangeEventType);
        window.dispatchEvent(urlChangeEvent);
      });
      // 監聽自定義的 URL 變化事件
      window.addEventListener(urlChangeEventType, function (event) {
        // 在這裡處理 URL 變化後的邏輯
        pageInit();
      });
      // 更新url引數
      function updateUrlWithNewParams(newParams) {
        // 獲取當前URL
        let url = window.location.href;
        let baseUrl = url.split("?")[0]; // 基礎URL
        let newParamsObj = new URLSearchParams(newParams); // 新的引數物件

        // 構造新的URL
        let newUrl = `${baseUrl}?${newParamsObj.toString()}`;

        // 使用history.pushState更新URL,不重新載入頁面
        window.history.pushState({ path: newUrl }, "", newUrl);
      }

      function getUrlParams(url = window.location.href) {
        const params = {};
        // 使用 URL 建構函式解析 URL
        const urlObj = new URL(url);
        // 獲取查詢字串
        const queryString = urlObj.search;
        // 使用 URLSearchParams 解析查詢字串
        const urlSearchParams = new URLSearchParams(queryString);

        // 遍歷所有引數並新增到物件
        for (const [key, value] of urlSearchParams.entries()) {
          params[key] = value;
        }

        return params;
      }

      function pageInit() {
        alert("修改url了");
        console.log("新引數", getUrlParams());
      }
    </script>
  </body>
</html>

相關文章