快速構建H5單頁面切換應用

在Web App和Hybrid App橫行的時代,爲了擁有更好的用戶體驗,單頁面應用順勢而生,單頁面應用簡稱`SPA`,即Single Page Application,就是隻有一個HTML頁面的應用程序,應用中全部的視圖都包含在這個HTML頁面中,並經過JavaScript控制相關視圖的顯示和隱藏,這種模式可讓用戶在Web App感覺Native App的速度和流暢。本篇文章的目的就是教你如何來快速的構建一個H5單頁面切換骨架。html

頁面設計

在構建SPA應用時,首先要肯定你的應用須要包含哪些視圖,在這裏,爲了可以說明問題,咱們只須要構建三個視圖,即 首頁、列表頁面和列表詳情頁面。 這三個頁面的邏輯關係是:git

  • 程序啓動,默認進入首頁
  • 點擊首頁的按鈕切換到列表頁面
  • 點擊列表頁面的按鈕切換到列表詳情頁面
  • 點擊返回按鈕或物理返回鍵可以回到上一頁。

首先咱們來看一下核心的HTML代碼:github

<body>
    <div class="pageview" style="background: #3b76c0" id="-main-view">
        <h3>首頁</h3>
        <div title="-list-view" class="right-arrow"></div>
    </div>
    <div class="pageview" style="background: #58c03b;display: none" id="-list-view">
        <h3>列表頁面</h3>
        <div class="left-arrow"></div>
        <div title="-detail-view" class="right-arrow"></div>
    </div>
    <div class="pageview" style="background: #c03b25;display: none" id="-detail-view">
        <h3>列表詳情頁面</h3>
        <div class="left-arrow"></div>
    </div>
</body>

class=`pageview`的div容器所包含的就是一個獨立的視圖頁面,在body中共有3個這樣的div,須要注意的是,第二、3個div都設置了style=`display:none`,惟獨第1個視圖沒有設置,這樣作的目的就是讓程序啓動時默認顯示首頁。web

在這段代碼中,用一個通用的CSS類來描述每個視圖的樣式以及切換效果,這個類就是`pageview`, 咱們先看看pageview是如何定義的:數組

.pageview{
   position: absolute;
   left: 0;
   top:0;
   width: 100%;
   height: 100%;
   overflow: hidden;
   -webkit-transition: 0.4s ease-out -webkit-transform;
}

在這裏,視圖頁面須要設置成絕對定位,而且和父容器等寬等高,這樣視圖纔可以平滑的進行切換,另外還須要設置頁面切換的過渡效果,咱們使用CSS3的transition屬性, 具體的參數就不在這裏作過多的講解了,你們應該都明白的。這個樣式類所產生的效果是:當改變-webkit-transform的值時,頁面會以樣式中定義的過渡效果進行平移,持續時間是0.4s. 到此爲止,主要的頁面設計已經完成了。瀏覽器

邏輯控制

要實現頁面切換,就要控制兩個頁面同時平移,即當前頁面不斷的離開屏幕,新的頁面不斷的進入屏幕。爲了方便描述,咱們把原來的頁面叫作`currentView`,把新的頁面叫作`applyView`,即申請進入的視圖。若是用transform來描述的話,currentView 須要從原來的0% 平移到-100%,即頁面向左平移了一個頁面寬度的距離,與此同時,appyView須要從原來的100% 平移到0%,恰好佔領currentView原來的位置,固然在平移以前,咱們須要設置好currentView和applyView的初始位置,分別須要設置成0%和100%。微信

// 頁面向左平移
var currentViewStart = "translateX(0%)", // currentView初始位置
   applyViewStart = "translateX(100%)", // applyView初始位置
   currentViewEnd = "translateX(-100%)",// currentView的最終位置
   applyViewEnd = "translateX(0%)";     // applyView最終位置

// 頁面向右平移
if (direction == "right") {
   currentViewStart = "translateX(0%)";
   applyViewStart = "translateX(-100%)";
   currentViewEnd = "translateX(100%)";
   applyViewEnd = "translateX(0%)"
}

咱們知道,經過JS操做就須要獲取頁面的DOM對象,爲了減小DOM的查詢,在頁面加載時,咱們將全部須要用到的頁面對象一次性查詢出來,並以鍵值對的形式存儲到Map對象中,當須要使用時,只須要根據key來獲取便可。app

//初始化執行
initViewPool:function(){
   var views = document.querySelectorAll(".pageview");
   // 經過call使用數組的forEach來遍歷NodeList
   Array.prototype.forEach.call(views,function(item){
       // viewPool是一個全局對象
       viewPool[item.id] = item; // 將DOM的id做爲鍵
   });
}

下面咱們將經過JS來控制頁面的切換效果:學習

// 獲取當前頁面的DOM對象
var currentView = viewPool[currentViewId];
// 獲取新頁面的DOM對象
var applyView = viewPool[pageId];

// 設置新頁面的初始位置
applyView.style.webkitTransform = applyViewStart;
// 設置當前頁面的初始位置
currentView.style.webkitTransform = currentViewStart;

// 設置新頁面顯示
applyView.style.display = "";

var t1 = setTimeout(function() {
   // 當設置最終位置時,頁面就會以過渡效果平移到最終位置
   applyView.style.webkitTransform = applyViewEnd;
   currentView.style.webkitTransform = currentViewEnd;
},200);

var t2 = setTimeout(function() {

   // 400ms後,頁面平移結束,設置currentView爲隱藏
   currentView.style.display = "none";
   // 將新頁面設置爲當前頁面
   currentViewId = pageId;

   if (direction === 'left') {
       window.location.hash = currentViewId.substring(1);
   }
   
   window.clearTimeout(t1);
   window.clearTimeout(t2);
},600);

在這裏有一個重要的操做就是:必定要將設置最終位置的操做放到定時器中,即t1, 這是由於當頁面被設置了初始位置後,須要必定的時間來`渲染`這個樣式,第2個定時器是爲了等待動畫執行完畢後進行相關的操做,好比設置當前頁面,設置hash,清除定時器等。當這段代碼被執行時,頁面就會以設定的效果進行平滑的移動,最終,當前頁面被隱藏,新頁面被設置爲當前頁面顯示到屏幕中央,這樣就完成了一次單頁面切換效果。動畫

支持物理鍵返回

既然是單頁面切換,就不得不提另一個問題,那就是物理返回鍵操做。其實,單頁面切換隻是頁面的顯示和隱藏操做,僅此而已,並非真正意義上的hash跳轉,而物理鍵返回其實是監聽瀏覽器的hash變化,所以爲了讓單頁面可以支持物理鍵返回操做,咱們須要模擬瀏覽器的hash變化,即當一個新頁面進入時,給當前地址加上一個#hash 的標識,當點擊物理返回鍵的時候,這個hash值會發生變化(回退到上一個hash),與此同時也會觸發一個hashchange事件,當監聽到hash變化時,咱們就經過JS切換到上一個hash對應的頁面,這樣就實現了物理返回鍵的效果。

if (direction === 'left'){
   //當進入到新頁面時,設置當前hash的值爲當前頁面的id
   window.location.hash = currentViewId.substring(1);
}

監聽hash變化的處理:

var that = this;
window.addEventListener("hashchange", function () {

   //當點擊返回鍵時,hash會回退到上一頁的hash值
   //獲取上一頁的hash值,並轉化爲對應view的id
   var id = window.location.hash.replace("#", "-");

   // 判斷當前頁面不是首頁,
   // 而且觸發的瀏覽器的`back`操做,即點擊返回鍵,由於頁面前進的時候也會發生hash變化
   if (currentViewId != "-main-view" && id != currentViewId) {
       id = id || "-main-view"; //若是上一頁是首頁,則hash爲空,這時須要補上對應的id
       //調用forward方法從當前頁面切換到上一頁
       that.forward(id, "right");
   }
}, false);

以上即是單頁面切換的基本思路,對應的完整示例代碼已上傳至 Github: https://github.com/git-onepixel/h5spa, 你能夠下載完整代碼進行調試和學習,若是須要查看效果演示,請點擊或使用微信掃一掃下面的二維碼進行訪問:

 

 

原創發佈 @一像素  2016.01

相關文章
相關標籤/搜索