HTML5 history


引入history.pushState的來龍去脈

大家都知道web2.0以來,大家都喜歡使用ajax來請求數據,提高用戶體驗,但是傳統的ajax可以無刷新改變頁面內容,但無法改變頁面URL,無刷新的改變頁面內容而url沒有改變導致搜索引擎無法抓取改變的頁面內容。

為了提高可訪問性,大家想了各種方法,比如說改變URL的hash,但是hash的方式不能很好的處理瀏覽器的前進、后退,為了能夠區分不同的hash,瀏覽器引入了onhashchange事件,但並在所有瀏覽器都支持onhashchange,對於不支持onhashchange事件的瀏覽器只能通過定時去判斷hash是否改變,而且搜索引擎不會理會井號,因此也就無法索引內容,這種方式顯然不夠靈活。

為此twitter和google約定了使用#!xxx(即hash第一個字符為!),引用了新的方式#!之后搜索引擎必須加以支持,比如說網址是http://example.com#!1,當搜索引擎發現上述網址是會自動解析成http://example.com?_escaped_fragment_=1,但是這種方式對用戶來說使用起來相當麻煩。

這時HTML5為了解決傳統ajax帶來的問題引入了新的API,即:history.pushState, history.replaceState

history.pushState

pushState是將指定的URL添加到瀏覽器歷史里,存儲當前歷史記錄點

 

API:history.pushState(state, title, url)

  1. // @state狀態對象:記錄歷史記錄點的額外對象,可以為空
  2. // @title頁面標題:目前所有瀏覽器都不支持
  3. // @url可選的url:瀏覽器不會檢查url是否存在,只改變url,url必須同域,不能跨域

 

history.pushState的目的

  • SEO優化
  • 更少的數據請求
  • 更好的用戶體驗

 

history.replaceState

replaceState是將指定的URL替換當前的URL,替換當前歷史記錄點

replaceState的api和pushState類似,不同之處在於replaceState不會在window.history里新增歷史記錄點,而pushState會在歷史記錄點里新增一個記錄點的

 

history.state

當前URL下對應的狀態信息。如果當前URL不是通過pushState或者replaceState產生的,那么history.state是null。

state對象雖然可以存儲很多自定義的屬性,但對於不可序列化的對象則不能存儲

 

window.onpopstate事件

window.onpopstate事件主要是監聽歷史記錄點,也就是說監聽URL的變化,但會忽略URL的hash部分。

history.go和history.back(包括用戶按瀏覽器歷史前進后退按鈕)觸發,並且頁面無刷的時候(由於使用pushState修改了history)會觸發popstate事件,事件發生時瀏覽器會從history中取出URL和對應的state對象替換當前的URL和history.state。通過event.state也可以獲取history.state

注意點:

  1. javascript腳本執行window.history.pushState和window.history.replaceState不會觸發onpopstate事件。
  2. 谷歌瀏覽器和火狐瀏覽器在頁面第一次打開的反應是不同的,谷歌瀏覽器奇怪的是回觸發onpopstate事件,而火狐瀏覽器則不會。

 

實例Demo

頁面css如下:

 body {
            overflow-x: hidden;
        }
        ul {
            padding: 0;
            margin: 0;
            list-style-type: none;
        }
        .header {
            font-weight: 18px;
            color: red;
            height: 100px;
            line-height: 100px;
            text-align: center;
        }
        .cho_link {
            background: url(../image/choose_bg.png) no-repeat;
        }

        .cho_search {
            width: 170px;
            margin-right: -20px;
            padding-right: 20px;
            *vertical-align: -2px;
        }

        .cho_box {
            border: 1px solid #bfbfbf;
            background-color: #ebebeb;
            *position: relative;
            overflow-y: hidden;
        }

        .cho_line {
            display: block;
            padding-top: 2px;
            background-color: #d2d2d2;
            border-bottom: 1px solid #f0f0f0;
        }

        .cho_left {
            width: 20%;
            margin-right: 10px;
            float: left;
            position: relative;
        }



        .cho_menu {
            padding-bottom: 72px;
            padding-top: 1px;
        }

        .cho_link, .cho_link_on {
            display: block;
            line-height: 32px;
            padding-left: 19px;
            color: #333;
            *zoom: 1;
        }

        .cho_link {
            background-color: #fafafa;
            border-bottom: 1px solid #f6f6f6;
            outline: none;
        }

            .cho_link:hover {
                background: #f6f6f6;
                border-bottom: 1px solid #e0e0e0;
                text-decoration: none;
            }

        .cho_link_on {
            margin: -1px -1px 0 0;
            background: #ebebeb;
            border-bottom: 1px solid #ccc;
            border-top: 1px solid #ccc;
            position: relative;
            cursor: default;
        }

            .cho_link_on:first-child {
                border-top: 0;
            }

            .cho_link_on:hover {
                text-decoration: none;
            }
View Code

 

頁面html代碼:

<div class="header">head</div>
    <div class="center">
        <!-- 左邊的選菜項 -->
        <div class="cho_left">
            <ul id="choMenu" class="rel cho_menu">
                <li><a href="ajax.aspx?area=pudong" class="cho_link cho_link_on">浦東區</a></li>
                <li><a href="ajax.aspx?area=baoshan" class="cho_link">寶山區</a></li>
                <li><a href="ajax.aspx?area=jiading" class="cho_link ">嘉定區</a></li>
                <li><a href="ajax.aspx?area=qingpu" class="cho_link">青浦區</a></li>
                <li><a href="ajax.aspx?area=minhang" class="cho_link">閔行區</a></li>
                <li><a href="ajax.aspx?area=putuo" class="cho_link">普陀區</a></li>
                <li><a href="ajax.aspx?area=jinshan" class="cho_link">金山區</a></li>
                <li><a href="ajax.aspx?area=songjiang" class="cho_link">松江區</a></li>
                <li><a href="ajax.aspx?area=zhabei" class="cho_link">閘北區</a></li>
                <li><a href="ajax.aspx?area=fengxian" class="cho_link">奉賢區</a></li>
                <li><a href="ajax.aspx?area=huangpu" class="cho_link">黃浦區</li>
                <li><a href="ajax.aspx?area=changning" class="cho_link">長寧區</a></li>
                <li><a href="ajax.aspx?area=jingan" class="cho_link">靜安區</a></li>
                <li><a href="ajax.aspx?area=zhoubian" class="cho_link">上海周邊</a></li>
            </ul>
        </div>

        <!-- 右側主列表 -->
        <div class="cell">
            <div id="listBox">
                右側顯示相應的內容
            </div>
        </div>
    </div>
    <div class="header">footer</div>

 

JS代碼:

//給每個左側鏈接綁定事件
        var eleMenus = $("#choMenu a").bind("click", function (event) {
            //獲得querystring的值
            var query = this.href.split("?")[1];
            //將左側列表鏈接全部去掉高亮
            $("#choMenu a").removeClass('cho_link_on');
            //給當前點擊的鏈接加高亮
            $(this).addClass('cho_link_on');
            //如果存在history.pushState狀態  且有queryString的值
            if (history.pushState && query) {
                var curText = $(this).text();
                //給右側內容框賦值
                $('#listBox').text(curText);
                // history處理

                document.title = "history demo-" + curText;
                if (event && /\d/.test(event.button)) {
                    //history.pushState使得頁面的URL地址變化了
                    history.pushState({ title: title }, title, location.href.split("?")[0] + "?" + query);
                }
            }
            return false;
        });

        var fnHashTrigger = function (target) {
            var query = location.href.split("?")[1], eleTarget = target || null;
            //頁面首次載入,沒有queryString的值
            if (typeof query == "undefined") {
                if (eleTarget = eleMenus.get(0)) {
                    // 如果沒有查詢字符,則使用第一個導航元素的查詢字符內容
                    history.replaceState(null, document.title, location.href.split("#")[0] + "?" + eleTarget.href.split("?")[1]) + location.hash;
                    fnHashTrigger(eleTarget);
                }
            } else {
                eleMenus.each(function () {
                    if (eleTarget === null && this.href.split("?")[1] === query) {
                        eleTarget = this;
                    }
                });

                if (!eleTarget) {
                    // 如果查詢序列沒有對應的導航菜單,去除查詢然后執行回調
                    history.replaceState(null, document.title, location.href.split("?")[0]);
                    fnHashTrigger();
                } else {
                    $(eleTarget).trigger("click");
                }
            }
        };

        if (history.pushState) {
            //頁面無刷新的,原先ajax請求的數據加載過來了  這就是popstate事件的作用
            window.addEventListener("popstate", function () {
                fnHashTrigger();
            });

            // 默認載入
            fnHashTrigger();
        }

 代碼大家可以復制過去自己試一下,代碼實現的功能是頁面的跳轉(前進后退,點擊等)不重新請求頁面,但是會相應改變右側區域的內容且url改變了,而且可以通過無刷新的請求回退狀態,真的是無限級的提高了用戶友好性。

 

瀏覽器支持情況


免責聲明!

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



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