前端路由的實現(三) —— History的pushState和replaceState用法

weixin_30455661發表於2018-04-24

HTML5中history提供的pushStatereplaceState這兩個API。它們提供了操作瀏覽器歷史棧的方法。

pushState能夠在不載入頁面的情況下改變瀏覽器的URL。這個方法接受三個引數:

狀態物件新狀態的標題可選的相對URL。

 history.pushState(data, null, '#/page=1');
    pushState接收3個引數,第一個引數為一個obj,表示瀏覽器的state屬性;
    第二個引數是document.title的值,一般設定為`null`;
    第三個引數string,用以改變當前url

 

pushState方法在改變url的同時向瀏覽器歷史棧中壓入新的歷史記錄

接收url的引數為string型別,用以改變當前位址列的url.需要注意的一點就是這個引數不能和跨域,即協議,域名,埠必須都是相同的,如果出現跨域的情況,即會提示:

Example:

其中 replaceState:

  replaceState接收的引數pushState相同,但是最終的效果是:位址列url會根據接收的引數而變化,但是瀏覽器並未在當瀏覽歷史棧中增加瀏覽器的歷史記錄,而是替換當前的瀏覽器歷史記錄。

通過pushStatereplaceState雖然能改變URL,但是不會主動觸發瀏覽器reload

window物件還提供 popstate方法

這個方法用以監聽瀏覽器在不同歷史記錄中進行切換,而觸發相應的事件

在瀏覽器提供的history物件上還有goback方法,用以模擬使用者點選瀏覽器的前進後退按鈕。在某個web應用當中,比如點選了<a>標籤,發生了頁面的跳轉。這時呼叫history.back()方法後頁面回退,同時頁面發生重新整理,這時window.onpopstate無法監聽這個事件。但是如果是通過pushState或者replaceState改變URL不發生瀏覽器重新整理的話,再使用history.back()history.go(),這樣popstate事件會被觸發

 

 

輸出如下:

注意:  通過pushState在url上新增?page=1可以通過location.search去獲取search的內容。不過如果通過location.search去改變url的話是會主動觸發瀏覽器reload的。

API大致瞭解了,那麼這些方法可以運用到哪些地方呢?一個比較常用的場景是就在單頁應用中,通過這些API完成前端的路由設計,利用pushStatereplaceState可以改變url同時瀏覽器不重新整理,並且通過 popstate 監聽瀏覽器歷史記錄的方式,完成一系列的非同步動作。

簡單的路由如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    a {color: red;text-decoration: underline;}
  </style>
</head>
<body>
  <a data-href="/post">post</a>
  <a data-href="/login">login</a>
  <script>
       const Router = [];
       const addRoute = (path ='', handle=() =>{}) => {
        let obj = {
          path,
          handle
        };
        Router.push(obj);
       }
       // 新增路由定義
       addRoute('/post', function(){
        // todo...
          alert('/post');
       })
       addRoute('/login', function(){
        // todo...
         alert('login');
       })
       // 路由處理
       const routeHandle = (path) => {
        for(var item of Router){
          if (item.path === path) {
            item.handle.apply(null, [path]);
            return true;
          }
        }
       }
       document.addEventListener('click', function(e) {
        let dataset = e.target.dataset;
        if(dataset) {
            if(routeHandle(dataset.href)) {
                var url = window.location.href;
                history.pushState({route: dataset.href}, null, oriUrl + dataset.href);
                //阻止預設行為
                return false;
                // e.preventDefault();
            }
        }
    })
  </script>
</body>
</html>

 

大致的實現思路就是,通過<a>新增路由資訊,然後攔截<a>標籤的預設行為,並與註冊的路由資訊進行匹配。若匹配成功呼叫對應的handle方法

轉載於:https://www.cnblogs.com/xuzhudong/p/8886752.html

相關文章