詳解H5中的history單頁面,手動實現單頁面開發,細說h5單頁面原理


就目前來看,前端的單頁面開發占了很大一部分,一方面無刷新的切換增強了體驗,並且瀏覽器記錄依然存在,前進后退都沒問題,在之前我們通地址欄中的hash改變來觸發onhashchange方法來實現單頁面應用,但是#的形式總是令人不爽,幸好h5新增了history.pushState與history.replaceState。

1.介紹API

history.pushState(data, title [, url]):

往歷史記錄堆棧頂部添加一條記錄; data會在onpopstate事件觸發時作為參數傳遞過去,title為頁面標題,當前所有瀏覽器都會 忽略此參數(我們在自己實現的時候可以隨便填寫),url為頁面地址,就是如果history.pushState({name:'home'},'home page' ,'home')則地址欄就成了/home,更神奇的是此時不會向后端發送請求,僅僅是url改變。

history.replaceState(data, title [, url]) :

更改當前的歷史記錄,參數跟history.pushState(data, title [, url])一致,只不過不會像瀏覽器歷史棧添加數據,而是替代之前的歷史記錄; 

history.state:用於存儲以上方法的data數據,

window.onpopstate:響應pushState或replaceState的調用;

 

2.介紹實現單頁面原理

通過以上幾個方法我們完全可以改變url並且監聽到url的變化,比如url由localhost:8000改變成localhost:8000/home,此時我們通過onpopstate監聽到了這個變化,並且拿到data數據,假設拿到了name,此時假設有以下對應路由表,其實可以隨便定義,

let route = {
    home:{
        name:'home',
        url:'./home.html',
        des:'home page'
    },
     class:{
         name:'class',
         url:'./class.html',
         des:'class page'
      }
}

  那我們就知道此時home對應應該是./home.html,於是我們利用ajax將./home.html加載過來,此時我們拿到了home.html的所有信息,於是跟vue或者其他框架一樣掛載到當前頁面的一個元素上。

注意點:

我們主動 利用history.pushState({name:'home'},'home page' ,'home')時候並不會觸發onpopstate,就是說此時是無法知道url變動了,為了讓頁面順利跳轉又觸發我們提供的ajax,那么我們就要修改一下history.pushState

var pushState = history.pushState;   // 存儲原生 replaceState
history.pushState = function(state, param) {     // 改寫 replaceState
        var urlName = arguments[2];
        var url = route[urlName].url;
        ajax(url)
        return pushState.apply(history, arguments);    // 調用原生的 replaceState
 };

  如上,我們不僅在使用 history.pushState時候,觸發我們自己定義的ajax函數,加載了頁面,又調用了原生的方法,是不會影響原生歷史記錄和跳轉等問題。

現在我們知道我們每次調用history.pushState都會觸發ajax函數

<div id="app"></div>

    <script>
        function ajax(url){
            //步驟一:創建異步對象
            var ajax = new XMLHttpRequest();
            //步驟二:設置請求的url參數,參數一是請求的類型,參數二是請求的url,可以帶參數,動態的傳遞參數starName到服務端
            ajax.open('get',url);
            //步驟三:發送請求
            ajax.send();
            //步驟四:注冊事件 onreadystatechange 狀態改變就會調用
            ajax.onreadystatechange = function () {
                if (ajax.readyState==4 &&ajax.status==200) {
                    //步驟五 如果能夠進到這個判斷 說明 數據 完美的回來了,並且請求的頁面是存在的
                 //輸入相應的內容
                    document.querySelector('#app').innerHTML = ajax.responseText
              }
            }
        }
    <script>

  利用這個ajax就可以將別的頁面的內容加載到本頁面的#app這個元素上,實現了單頁面跳轉。

3.需要注意的地方和坑:

1.在嘗試該方法前,需要其啟動服務器代理html文件,即靜態的html文件打開會報錯

2.我們在通過history.pushState改變url瀏覽器並不會跟處理普通url一樣新發送請求,但是我們在刷新的時候瀏覽器還是會發送請求,即localhost:8000/home刷新瀏覽器就會請求這個接口,就會導致后台根本沒有這個路由返回404,(這也是vue-route經常會出現刷新404問題的原因)解決辦法就是遇到404的都代理給index.html,我測試使用express來起服務的,有一個插件叫 connect-history-api-fallback,使用之后就不會出現這個問題

如果有想要自己嘗試的,這里附上我們demo:https://github.com/jiangzhenfei/h5History,下載還只要執行node server.js即可,打開瀏覽器就可以嘗試了。

 


免責聲明!

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



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