前言
在上一篇文章『監聽 hash change 事件方法』中簡單的提到我們該如何監聽網址的Hash值改變,在本文章中我們將會利用這項技術,實際完成Single Page Application(SPA)的基本架構,有著這樣的架構,我們就能夠使用ajax的方式更新畫面,而不需要將整個畫面重新載入。
這個系統會實作以下功能 :
如果你還不了解SPA你可以參考『Single-page application』
這個系統會實作以下功能 :
- 使用hashchange plugin監聽Hash改變事件
- 使用jQuery動態載入外部html
- 使用jQuery.on動態綁定外部html
如果你還不了解SPA你可以參考『Single-page application』
監聽Hash改變
首先我們先來完成監聽Hash事件的程式碼,如下
$(document).ready(function(){
$(window).hashchange( function(e){
var hash = window.location.hash;
});
$(window).hashchange();
});
撰寫UI介面
介面部分預期提供三個按鈕,分別可以連結到三個不同的頁面,將外部頁面讀取到page-container容器中,page-container會自動切換該顯示哪一個page,其它以載入的頁面會被隱藏起來。如下程式碼
<body>
<h1>Single Page Application Sample</h1>
<ul>
<li>
<a class="nav" href="#main" data-role="url">Main</a>
<a class="nav" href="#code" data-role="url">程式碼</a>
<a class="nav" href="#about" data-role="url">About</a>
</li>
</ul>
<!--存放頁面的容器-->
<div id="page-container">
</div>
</body>
Ajax載入外部頁面
我們已經可以監聽Hash改變事件以及PageContainer架構,下一步就把監聽到的Hash值對應到外部HTML檔案載入,在這裡我們使用jQuery來實作。jQuery提供load方法讓我們能夠載入外部的元素到容器內,範例如下
透過這個方法,我們將載入外部HTML放入PageContainer寫成一個函式
appendPage(pageid)
完成了!!
打開網頁試試看,當我們按下超連結切換頁面,你會發現新的頁面會載入到page-container裡面,如果該頁面已經載入,就會直接切換進去。
到目前為止一切都完成了,頁面已經可以動態的載入近來,但是好像忘了甚麼??
好像叫....事事事『事件』!!沒錯,如果你有拿上述的程式碼擴充,你會發現外部載入的頁面就算我們事先在$.ready()內綁上事件處理但仍然無法觸發,原因很簡單因為使用ajax載入的畫面在$(document).ready()中並還沒載進來,所以我們必須做小小個修正。
每當有Page被外部讀進來時,就觸發pagecreate事件,當Page切換顯示時觸發pageshow事件;有了這個機制,我們可以在$(document).ready()中監聽這些事件,然後在pagecreate事件發生裡去綁上該頁面的元素事件,修改後程式碼如下 :
appendPage修正
$(document).ready()修正
範例程式下載
// param1 : extend html url
// param2 : callback function
$result = $page.load(id + '.html', function(){});
透過這個方法,我們將載入外部HTML放入PageContainer寫成一個函式
appendPage(pageid)
function appendPage(id){
var $container = $('#page-container');
var $innerpage = $container.find('#' + id);
console.log($innerpage);
if($innerpage.length == 0){
var $page = $('<div class="page"></div>').attr('id', id);
$result = $page.load(id + '.html', function(){
$result.appendTo($container);
$page.siblings('.page').hide();
$page.hide().fadeIn(500);
});
}
else{
$innerpage.siblings('.page').hide();
$innerpage.fadeIn(500);
}
}
修改監聽Hash function,加入appendPage
$(window).hashchange( function(e){
var hash = window.location.hash;
var pageid = location.hash.substring(1);
// 預設沒填寫載入首頁
if(!hash)
appendPage("main");
else
appendPage(pageid);
});
$(window).hashchange();
完成了!!
打開網頁試試看,當我們按下超連結切換頁面,你會發現新的頁面會載入到page-container裡面,如果該頁面已經載入,就會直接切換進去。
到目前為止一切都完成了,頁面已經可以動態的載入近來,但是好像忘了甚麼??
好像叫....事事事『事件』!!沒錯,如果你有拿上述的程式碼擴充,你會發現外部載入的頁面就算我們事先在$.ready()內綁上事件處理但仍然無法觸發,原因很簡單因為使用ajax載入的畫面在$(document).ready()中並還沒載進來,所以我們必須做小小個修正。
每當有Page被外部讀進來時,就觸發pagecreate事件,當Page切換顯示時觸發pageshow事件;有了這個機制,我們可以在$(document).ready()中監聽這些事件,然後在pagecreate事件發生裡去綁上該頁面的元素事件,修改後程式碼如下 :
appendPage修正
function appendPage(id){
var $container = $('#page-container');
var $innerpage = $container.find('#' + id);
console.log($innerpage);
if($innerpage.length == 0){
var $page = $('<div class="page"></div>').attr('id', id);
// 可能會有一些動畫,所以pagecreate會比pageshow更快觸發
// pagecreate重頭到尾只有在page第一次被讀取進來時才會觸發
// pageshow每次切換頁面都會觸發
// 所以一些按鈕的事件初始化因該寫在pagecreate
$result = $page.load(id + '.html', function(){
$result.appendTo($container);
$page.trigger('pagecreate', [$page]);
$page.siblings('.page').hide();
$page.hide().fadeIn(500, function(){
$page.trigger('pageshow', [$page]);
});
});
}
else{
$innerpage.siblings('.page').hide();
$innerpage.fadeIn(500, function(){
$innerpage.trigger('pageshow', [$innerpage]);
});
}
}
$(document).ready()修正
$(document).ready(function(){
$(window).hashchange( function(e){
var hash = window.location.hash;
var pageid = location.hash.substring(1);
if(!hash)
appendPage("main");
else
appendPage(pageid);
});
$(window).hashchange();
$("#page-container").on('pageshow', '#main', function(event, $page){
showNoty("main頁面顯示", "success");
});
$("#page-container").on('pageshow', '#code', function(event, $page){
showNoty("code頁面顯示", "success");
});
$("#page-container").on('pageshow', '#about', function(event, $page){
showNoty("about頁面顯示", "success");
});
$("#page-container").on('pagecreate', '#main', function(event, $page){
$("#main-btn").click(function(){
showNoty("你點擊了Main頁面的按鈕!!", "error")
});
showNoty("main頁面被創建", "error");
});
$("#page-container").on('pagecreate', '#code', function(event, $page){
$("#contact-btn").click(function(){
showNoty("你點擊了code頁面的按鈕!!", "error")
});
showNoty("code頁面被創建", "error");
});
$("#page-container").on('pagecreate', '#about', function(event, $page){
$("#about-btn").click(function(){
showNoty("你點擊了About頁面的按鈕!!", "error")
});
showNoty("about頁面被創建", "error");
});
$("a[data-role=url]").click(function(e){
e.preventDefault();
console.log(e);
var hash = e.target.hash;
window.location.hash = hash;
})
});
範例程式下載
Dropbox載點
DEMO網址
結論
在本文章中我們透過實戰了解SPA的原理與實現方式,在HTML5中提供了一個更能夠控制頁面的技術『History API』,但基於流覽器相容性問題,目前該技術尚未成為主流,在下一篇文章中我們將介紹HistoryAPI的操作方式,並了解如何使用History.js(plugin)實現跨瀏覽器的HistoryAPI。
沒有留言:
張貼留言