之前一直很好奇阴挣,SPA應(yīng)用到底是怎么實現(xiàn)的,昨天無意間看到了有一篇介紹的文章登钥,就想著來試一下水(以下根據(jù)我的理解所寫畔师,可能會讓你看的云里霧里,如果想加深了解牧牢,最好先了解下window.location.hash是什么東西)
其實看锉,SPA的原理就是,一開始將一些必要的頁面都加載進(jìn)來结执,當(dāng)你在頁面輸入別的路由的時候度陆,其實還是待在當(dāng)前的頁面,只不過是他識別出你想要去的地址献幔,然后將那個頁面的內(nèi)容獲取到,替代掉當(dāng)前頁面的內(nèi)容趾诗,并且相應(yīng)的改變url地址蜡感,這樣給人看起來就好像到了另一個頁面蹬蚁,實際上你還是在這個頁面里,沒有離開過.
比如郑兴,例如當(dāng)前你在localhost:8080/index.html這個頁面時犀斋,你想跳轉(zhuǎn)到#list-view頁面(使用hashChange),或者你點(diǎn)擊某個跳轉(zhuǎn)按鈕要跳轉(zhuǎn)到那個頁面的時候情连,他先獲取你那個#list-view頁面的內(nèi)容叽粹,然后將當(dāng)前頁面的內(nèi)容清除掉,然后再把list-view的內(nèi)容呈現(xiàn)出來却舀,并沒有跳轉(zhuǎn)到別的頁面虫几,你從頭到尾都是在這個頁面里,不過url地址會變化挽拔,因此看起來就像你到了另一個頁面辆脸,這樣給人的用戶體驗特別好,因為不需要等待頁面加載過程.
說了這么多螃诅,我們來根據(jù)他的原理做一個SPA的小應(yīng)用吧(里面的html和css代碼直接復(fù)制了我之前看的那個博客的作者的啡氢,因為懶得自己設(shè)計)
html代碼如下:
<!DOCTYPE html>
<html>
<head>
<title>SPA</title>
<link rel="stylesheet" type="text/css" href="index.css" />
<script type="text/javascript" src="jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="spa.js"></script>
</head>
<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>
</html>
在這里,我們先創(chuàng)建了三個div,第一個main-view的display不設(shè)置术裸,其他的兩個display設(shè)置為node,這樣我們一開始進(jìn)去就只能看到main-view這個頁面
之后倘是,我們可以通過js代碼來模擬SPA對路由跳轉(zhuǎn)的處理
var states ;
var currentState;
$(document).ready(function() {
states = registState();
currentState = init();
//監(jiān)聽hash路由變化
window.addEventListener("hashchange", function() {
var nextState;
console.log(window.location.hash);
//判斷地址是否為空,若為空袭艺,則默認(rèn)到main-view頁面
if (window.location.hash == "") {
nextState = "main-view";
}
else {
//若不為空搀崭,則獲取hash路由信息,得到下一個狀態(tài)
nextState = window.location.hash.substring(1);
}
//判斷當(dāng)前狀態(tài)是否注冊過(是有存在這個狀態(tài))0g
var validState = checkState(states, nextState);
//若不存在匹表,則返回當(dāng)前狀態(tài)
if (!validState) {
console.log("you enter the false validState");
window.location.hash = "#" + currentState;
return;
}
$('#'+ currentState).css("display", "none");
$('#'+ nextState).css("display", "block");
currentState = nextState;
})
})
//狀態(tài)注冊
function registState() {
var states = [];
//狀態(tài)注冊
$(".pageview").map(function() {
return states.push($(this)[0].id);
})
return states;
}
//初始化门坷,對用戶一開始輸入的url進(jìn)行處理
function init() {
var currentState = window.location.hash.substring(1);
if (currentState == "") {
currentState = "main-view";
}
if (currentState != "main-view") {
$('#main-view').css("display", "none");
$('#'+ currentState).css("display", "block");
}
return currentState;
}
//判斷狀態(tài)是否存在
function checkState(states, nextState) {
var tof = false;
states.forEach(function(element) {
if (element == nextState) {
tof = true;
}
})
return tof;
}
這里,我們首先將每一個div當(dāng)做一個狀態(tài)袍镀,當(dāng)用戶輸入的地址匹配了某個狀態(tài)之后默蚌,就呈現(xiàn)那個狀態(tài)所代表的頁面(每個div的狀態(tài)名我們設(shè)置為他們的id名字)
代碼我覺得還算比較清晰,首先苇羡,我們就先注冊這三個div的狀態(tài)(registState)绸吸,然后根據(jù)用戶輸入的url地址來初始化頁面,返回匹配的那個狀態(tài)的頁面(init)设江。
并且锦茁,注冊一個hashchange事件,這個事件是當(dāng)用戶輸入的hash地址變化后觸發(fā)叉存,我們在里面獲取用戶的輸入地址码俩,然后返回匹配的那個狀態(tài)的頁面,若沒有匹配的狀態(tài)歼捏,則返回上一個匹配的狀態(tài)稿存。以下的截圖
值得一提的是笨篷,我里面替換頁面的做法是:將當(dāng)前狀態(tài)的頁面的display設(shè)置為none,然后將下一個狀態(tài)的頁面的display設(shè)置為block,這樣就完成了頁面的替換以及路由的變換,而且不會導(dǎo)致路由的變化
初始頁面:
修改路由地址瓣履,修改為file:///C:/Users/chenjg/Desktop/Interest/SPA/index.html#list-view,可以看到頁面發(fā)送了相應(yīng)的變化
輸入錯的地址率翅,沒有匹配到合適的狀態(tài),則恢復(fù)到上一個狀態(tài):file:///C:/Users/chenjg/Desktop/Interest/SPA/index.html#list-vi
接下來打算繼續(xù)試下路由的嵌套袖迎,以及動態(tài)加載html文件作為路由的模塊冕臭。
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者