實現前端路由的兩種方式及其差異


前端路由

前端路由的本質是監聽url變化,然后匹配路由規則,無需刷新就可以顯示相應的頁面,目前單頁面路由主要有兩種方式

  • hash 模式
  • history 模式

hash模式實現路由

為什么要使用hash模式:頁面使用Ajax發送異步請求可以實現無縫刷新,但這種方式也存在使得瀏覽器的url不發生任何變化的時候就完成了請求,使得用戶體驗不佳,也導致了用戶下次使用相同的url訪問上次的頁面時內容無法重新呈現的問題。hash模式是解決這個問題的途徑之一。
主要通過location.hash設置hash Url,也就是url的符號#后面的值。當哈希值發生變化時,不會向服務器請求發送數據,可以通過hashchange事件來監聽hash的變化,實現相應的功能

  • location.hash 設置/獲取hash
  • hashchange事件監聽url變化,解析url實現頁面路由跳轉

hash模式需要注意的幾個點

  • 散列值不會隨請求發送到服務器
  • 散列值會反映在瀏覽器url上
  • 只修改瀏覽器的哈希部分,按下回車,瀏覽器不會發送任何請求給服務器,只會觸發hashchange事件並且修改location.hash的值
  • html a標簽,設置id錨點,點擊觸發時,瀏覽器會自動設置location.hash值,同時觸發hashchange事件,url上也會反映這一變化
  • hash模式下,手動刷新頁面不會向瀏覽器發送請求,不會觸發hashchange事件,但是會觸發load事件

示例1:location.hash觸發hashchange事件


<body>
    <button id="add">add hash</button>
    <button id="update">update hash</button>
    <script >
        var i = 1;
        document.querySelector("#add").addEventListener('click',()=>{
            location.hash = "abc" + i++;//http://xxx.html#abc 哈希必有#
        });
        document.querySelector("#update").addEventListener('click',()=>{
            location.hash = "efg" + i++;
        });
        //監聽hash的變化
        addEventListener("hashchange",()=>{
            console.dir(location.hash);
        })
    </script>
</body>

效果

示例2:錨點跳轉設置hash觸發hashchange事件

關於錨點跳轉:

  • a標簽可以跳轉到指定了name或者id的a標簽
  • a標簽可以跳轉到指定了id的非a標簽,非a標簽如果沒有指定id則不可以被跳轉
<body>
    <a name="target1" >a name target1</a>
    <div style="width: 100%; height: 500px;background-color: salmon;"></div>
    <div id="target2" >div id target2</a>
    <div style="width: 100%; height: 1500px;background-color: salmon;"></div>
    <a href="#target1">跳轉指定name的a標簽</a>
    <a href="#target2">跳轉指定id的div</a>
    <script >
        //監聽hash的變化
        addEventListener("hashchange",()=>{
            console.dir(location.hash);
        })
    </script>
</body>

效果

history模式實現路由

history對象

window.history屬性指向history對象,它表示當前窗口的瀏覽歷史
history對象保存了當前窗口訪問過的所有頁面網址,以下是常用API
-history.length:返回歷史記錄中的網頁數量
-history.forward():前進
-history.back():后退
-history.go(num):前往相對於自身的第num個(前后取決於正負)頁面
-history.state:history堆棧最上層的狀態值
-history.pushState(stateObj,title,url):向當前歷史記錄插入一個狀態值對象stateObj,並在網址后面添加url,title無實際意義
-history.replaceState(stateObj,title,url):修改history對象的當前記錄

事件
-poptate:僅當瀏覽器動作出現時(前進、后退)才觸發,pushState和replaceState方法並不會觸發該事件,其回調函數參數event的state屬性指向當前歷史記錄的state對象

history模式實現路由

history對象

window.history屬性指向history對象,它表示當前窗口的瀏覽歷史
history對象保存了當前窗口訪問過的所有頁面網址,以下是常用API
-history.length:返回歷史記錄中的網頁數量
-history.forward():前進
-history.back():后退
-history.go(num):前往相對於自身的第num個(前后取決於正負)頁面
-history.state:history堆棧最上層的狀態值
-history.pushState(stateObj,title,url):向當前歷史記錄插入一個狀態值對象stateObj,並在網址后面添加url,title無實際意義.
-history.replaceState(stateObj,title,url):修改history對象的當前記錄

事件
-poptate:僅當瀏覽器動作出現時(前進、后退)才觸發,pushState和replaceState方法並不會觸發該事件,其回調函數參數event的state屬性指向當前歷史記錄的state對象

history實現路由

主要通過history.pushState/replceState向當前歷史記錄中插入狀態對象state,在瀏覽器前進、回退、跳轉等動作發生時觸發popState事件,此時可以通過解析popState事件回調函數的event參數中的state對象,或者解析當前頁面url來實現路由。
建議解析url方式實現路由。如果沒有在頁面首次加載的時候設置pushState/replaceState,那么首頁一般是沒有state對象的,在執行瀏覽器動作時,如果回退到首頁,那么當前history對象的state屬性不存在,導致解析state報錯

<body>
    <button id="add">add state</button>
    <button id="update">replace state</button>
    <script>
        var i = 1;
        document.querySelector("#add").addEventListener('click', () => {
            history.pushState({curState:i},'title','#page'+i);
            i++;
        });
        document.querySelector("#update").addEventListener('click', () => {
            history.replaceState({curState:i},'title','#page'+i);
            i++
        });
        //監聽history動作 
        addEventListener("popstate", () => {
            console.dir(history.state.curState);
        })
        //監聽hash的變化
        addEventListener("hashchange",()=>{
            console.dir('hashchange event: ',location.hash);
        })
    </script>
</body>

效果:

兩種路由方式的差異以及需要注意的點

方式的異同

  • 頁面手動刷新,hash模式不會向服務器發送請求,history模式會
  • hash模式下url中的哈希值不會發送到服務器,history模式url全部會發送至服務器
  • 設置location.hash和pushState都不會導致瀏覽器刷新
  • 設置location.hash的時候會觸發hashchange事件和popstate事件
  • 僅當pushState函數設置url參數的值為hash格式時,瀏覽器動作發生會觸發hashchange事件,盡管location.hash值為空
  • a標簽錨點跳轉可以設置hash,觸發hashchange事件

pushState設置跨域請求

如果pushState的url為跨域網址,那么會報錯.這樣設計的目的是防止惡意代碼讓用戶以為他們是在另一個網站上


免責聲明!

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



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