看標題是不是感覺很拽的樣子,其實沒什么啦,也就是時下常說的單頁面應用。這種web形式在如今的移動端十分流行,畢竟在移動端頻繁得去刷新界面不是很友好,而且還費流量。今天我們要做一個小的app(移動端),來揭秘history的秘密。首先我們了解一下核心方法:
window.history.pushState:方法:為histroy建立歷史記錄,該方法傳入三個函數:1、對應url的信息2、下一個界面的title 3 、需要你動態改變的地址欄中德url.
window.history.state:屬性:當前的history中的信息狀態。
window.history.replaceState:方法:以本次信息替換之前的history內容記錄,傳入的參數與第一個相同。
首先,你不必執着於上面的一些定義。在我第一次看到這些說明的時候我也是一頭霧水,真正了解他們是在使用它們之后。事不宜遲,我們首先創造出html結構來:
要實現簡單的界面切換,我們首先要創建出三個界面,當然為了方便,這三個界面就是是三個div(a,b,c 整屏大,絕對定位)和一個按鈕(用來添加歷史內容記錄):
<!DOCTYPE html> <html> <head> <title>history back</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <script type="text/javascript" src="zepto.js"></script> <link rel="stylesheet" type="text/css" href="history.css"> </head> <body> <div class="a"><p>What we talk about when we talk about love</p><span>A</span></div> <div class="b none"><p>Quell nous sommes parlons lorsqur nous parlons d'amour</p><span>B</span></div> <div class="c none"><p>當我們在談論愛情的時候,我們在談論些什么</p><span>C</span></div> <button class="forward">FORWARD</button> </body> </html>
翻頁效果,可以簡單一些,在這里,我做了動畫,利用css3的3d動畫屬性,打造簡單的動畫效果。如果你覺得麻煩,可以直接元素的顯示和隱藏,但在實際的項目中,我推薦利用動畫過度效果,這樣不僅提高客戶體驗,而且你可以利用到css3的許多新特新,對於web2.0時代的前端精英來說這是必修課。下面是切換效果的css代碼:
@-webkit-keyframes sliderightout{from{-webkit-transform:translateX(0px);}to{-webkit-transform:translateX(50%);}} @-webkit-keyframes slideleftin{from{-webkit-transform:translateX(-50%);}to{-webkit-transform:translateX(0px);}} @-webkit-keyframes slideleftout{from{-webkit-transform:translateX(0px);}to{-webkit-transform:translateX(-50%);}} @-webkit-keyframes sliderightin{from{-webkit-transform:translateX(50%);}to{-webkit-transform:translateX(0px);}} .slideleftout{-webkit-animation:slideleftout 350ms ease-in-out;} .slideleftin{-webkit-animation:slideleftin 350ms ease-in-out;} .sliderightout{-webkit-animation:sliderightout 350ms ease-in-out;} .sliderightin{-webkit-animation:sliderightin 350ms ease-in-out;} .animatestart{position:absolute;top:0;left:0;z-index:3;width:100%;height:100%;overflow-x:hidden} .animatestart.page-container{overflow-x:hidden;-webkit-transform:translate3d(0,0,0);-webkit-backface-visibility:hidden;background-color:#f5f5f5}
然后是控制界面各個元素的顯示位置的css代碼,排列組合各個界面(div p button span)。
*{ padding: 0; margin: 0; } .none { display: none; } div { position: absolute; height: 100%; width: 100%; color: #fff; } div span { display: block; font-size: 6.5em; text-align: center; } div p { font-size: 1.2em; } button { position: absolute; height: 40px; width: 100px; border-radius: 6px; background: #fff; bottom: 50px; border: 0; } button.back { left: 20px; } button.forward { right: 20px; } .a { background: #19a39e; } .b{ background: rgb(245, 81, 81); } .c{ background: rgb(71, 142, 30); }
接下來是重點,我們的思路是首先給瀏覽器的歷史填充記錄,這個需要手動完成,這也就是button的使命,因此,我們首先綁定forward按鈕:
//首先給history添加一條記錄,使得第一個界面和后來的界面看起來是永遠的以page=x結尾 window.history.pushState({info:'a'}, 'Page', '?page=a'); //數據源 var source = [ {cls:'a', url:'?page=a'}, {cls:'b', url:'?page=b'}, {cls:'c', url:'?page=c'} ], //數據源的下表, k = 0, //界面漲勢的屬性列表 index = ['a', 'b', 'c'], //記錄每個界面跳轉的順序的列表 stoage = []; //綁定按鈕的tap事件,我們在移動端做測試,用的是tap,zepto會幫我們轉譯該事件 $('.forward').on('tap', function(){ if(source[k]) { //取下一個界面的數據源 var m = source[++k]; //在這里填充history記錄,pushstate是方法是不會引起界面刷新的,但是卻會改變瀏覽器的回退/前進行為,執行這一步的時候可以看到地址欄中的url變化了。 window.history.pushState({info:m.cls}, 'Page', m.url); //儲存該節目名稱到stoage列表中 stoage.push(window.history.state.info); //下面是切換的動畫,因為這里力求簡單做的是一直向前走的動作,所以動畫是從右到左的切換順序 $('.' + m.cls).removeClass('none').addClass("animatestart sliderightin"); setTimeout(function(){ //動畫結束時重置class $('.'+ source[k -1].cls).addClass('none'); $('.' + m.cls).removeClass('animatestart sliderightin'); }, 350); } })
上面做的事情,還僅僅是在界面中利用dom事件跳轉界面,要利用前進和后退按鈕實現無刷新跳轉節目我們需要偵聽popstate事件,也就是回退/前進行為的事件:
//利用stoage的存儲和index列表中的先后規則,放回動畫翻轉順,是從左到右,還是從右到左 function j() { var l = stoage.length; if(index.indexOf(stoage[l-2]) < index.indexOf(stoage[l-1])) { return 'animatestart sliderightin'; }else{ return 'animatestart slideleftin'; } } //開始監聽瀏覽器的前進/后退行為 $(window).on('popstate', function(state) { //移除按鈕 $('.forward').remove(); //將本界面名稱存入stoage列表中 stoage.push(window.history.state.info); //取得上一個界面的名稱 var thiscls = stoage[stoage.length - 2]; //取得當前界面的名稱 var nextcls = stoage[stoage.length - 1]; //對比兩個界面獲得動畫效果 var cls = j(); //執行動畫效果 $('.' + nextcls).removeClass('none').addClass(cls); setTimeout(function(){ //動畫結束時重置clas $('.'+ thiscls).addClass('none'); $('.' + nextcls).removeClass(cls); }, 350); });
通過點擊按鈕,這時候看到,瀏覽器的回退按鈕已經可以啟用,我們點擊回退,觀察url的變化和界面的切換變化
page=c變成了page=b,動畫效果是從左到右,界面就這樣切換成功,界面並無刷新,多試幾次。
A->B
B->C
這樣我們就實現了點擊回退/前進按鈕實現單界面無刷新切換了。
事情還有另一種做法,即使利用hash變化監聽onhashchange來實現無刷新的界面切換,你一定想到了backbone就是這樣做的。不過對於小一點的項目,我建議用'?'(傳值)不是'#'號(hash),因為無刷下跳轉意味着和利器ajax一起使用,使用‘?’號的好處是,即使用戶強制刷新了界面,我們也可以給后台傳參數,告訴后台我們正處於哪一個界面,需要什么樣的數據,從而和前段的ajax統一起來。因為?號代表search,刷新的時候給后台會傳入get類型的數據的。而#號(hash值)卻並不會這樣做。當然,你可以使用你的聰明才智改變這種情況,那就見仁見智了。