前端路由實現常用的兩種思路,history和hash

路由的實現方式

1,利用監控錨點hash的變化實現前端路由思路, (參考hash.html)
是通過錨點來改變瀏覽器的URL,體現在URL後面會加上#,並且可以通過window.onhashChange來監聽這一變化,從而我們可以建立好hash值和對應回調函數的映射關係,然後可以通過點擊a標籤,實現在不刷新頁面情況下,通過ajax發送請求獲取異步數據來改變頁面的結構。
  • 優點—實現方式較爲簡單,有現成的hashChange來監聽路由哈希變化,兼容性較好,大部分瀏覽器支持
  • 缺點—’#'不太美觀;由於Hash對於服務端來說是不可見的,所以對於SEO不友好
2,利用History具體實現前端路由思路 參考鏈接(history.html)
首先路由的切換可能由這麼幾個行爲引起,我們需要做不同的處理。
  • 點擊a鏈接
    這種方式只需要在他的onclick事件先阻止他的默認跳轉行爲,然後獲取他的url,調用pushState/replaceState改變URL,然後根據url和回調函數的映射關係,觸發相應的動作

  • 直接在腳本中調用pushState/replaceState
    點擊瀏覽器的前進/後退按鈕,這裏需要用到另一個事件,onpopState, 當激活瀏覽器歷史記錄時會被觸發,注意這個事件不會被pushState/replaceState觸發,這個事件回調會可以獲取到當前路由下我們之前通過pushState/replaceState存入的信息,也可以拿到url信息,然後根據映射關係去執行回調。

history 擴展

  • 後退一個記錄window.history.back() 前進一個記錄window.history.forward()
  • 跳轉第n次記錄 window.history.go(n) 。 window.history.go(-1) 相等於window.history.back(),
  • window.history.go(1) 相等於 window.history.forward(), window.history.go(0) 相等於 刷新
  • pushState() 用於向history對象添加當前頁面的記錄,並且改變瀏覽器地址欄的URL。
  • onpopstate事件,該事件在窗口歷史記錄改變時被觸發。

hash.html

<!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>
    <header>
         <a href="#/">首頁</a>
         <a href="#/friend">朋友圈</a>
         <a href="#/my">個人中心</a>
    </header>
    <div id="content">
        
    </div>
</body>
<script>
    window.onload = function(){
        updateContent() 
    }

    let contentObj = document.querySelector('#content')
    window.addEventListener('hashchange',function(){
       updateContent()      
    })

    function updateContent(){
       let hash = window.location.hash;
       console.log(hash);
       if(hash === '#/'){
           contentObj.innerHTML = '首頁'
       }else if(hash === '#/friend'){
           contentObj.innerHTML = '朋友圈'
       }else if(hash === '#/my'){
           contentObj.innerHTML = '個人中心'
       }  
    }
</script>
</html>

history.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>前端路由實現</title>
</head>

<body>
    <div>
        <div class="nav">
           <a href="javascript:void(0)" data-path="index">首頁</a>
           <a href="javascript:void(0)" data-path="news">新聞</a>
           <a href="javascript:void(0)" data-path="about">關於</a>
        </div>
        <div id="router">
            <!-- 內容加載區域 -->
        </div>
    </div>

    <script>
        (function () {
            history.replaceState(null, null, ''); //最開始的狀態,採用replace直接替換
            document.querySelector('#router').innerHTML = '<p>首頁</p>'
            
            var allLinks = document.getElementsByTagName('a');
            var urlArr = window.location.href.split('?');
            var currentRouter = urlArr[urlArr.length - 1]
            currentRouter  = currentRouter ? currentRouter : 'index';
            for(var i=0;i<allLinks.length;i++){
                var allLinkItem = allLinks[i];
                var path = allLinkItem.getAttribute('data-path');
                allLinkItem.addEventListener('click', function () {
                    var text = this.text;
                    document.querySelector('#router').innerHTML = '<p>' + text + '</p>';
                    var url = this.getAttribute('data-path');
                    history.pushState(null, null, '?' + url);
                    // window.location.href = "http://localhost:3000/history.html?"+url;
                })
                if(path === currentRouter){
                    allLinkItem.click();
                }
            }

        })()
    </script>

</body>

</html>

參考鏈接 https://blog.csdn.net/u014298440/article/details/87467056

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章