一、前言
其實不止一次想監聽瀏覽器的回退方法,比如
在 list.html 頁滾動加載了幾頁列表,點到 detail.html 看詳情,反回來時又得重新加載幾頁
H5 有背景音樂的,跳頁就得重新放,體驗實在不妙,等等
再其他就是體驗上的優化了,雖然可以添加返回按鈕,但手機的回退鍵還是很常用的。
再加上 ajax 的無刷新體驗,單頁面應用可謂是一大裝逼利器。
二、前端路由的好處
(偽)換頁面時還可以添加動畫,絲滑流暢的操作體驗實在不能更棒,另外相較后端路由,前端路由也算是減輕了服務區負荷...
也正基於此,根據不同 url 渲染不同視圖這種路由的概念被提上台面,讓渲染哪一個可以得到方便的管理。
三、前端路由的壞處
前端路由也是有利有弊,它的不足在於
1. 安全性,改改路由就能跳到某頁面,肆意進入不同流程,想想還是有點瘮人的
2. 狀態恢復,比如第一頁添了表單,跳到第二頁再返回,這些表單可能得清空之類的問題
四、實現前端路由
其實路由也就兩步,實現 url 變化 & 捕捉變化進行不同的頁面邏輯
1. 改變 url
location api 的 reload / replace 方法,修改 href / hash / search 等屬性等,
history api 的 back / go 方法,以及比較新的 pushState / replaceState 方法...
改變 url 的方式太多了,
需要注意的是哪些是會刷新頁面的,哪些是會改 url 但不刷新頁面的...
2. 捕捉 url 變化
主要得靠 window 的事件 hashchange 和 popstate
用 setInterval 持續監聽(每 100ms 比較 oldUrl 和 nowUrl)也不是不可以,但你也懂得性能是個好東西
注意:pushState / replaceState 不會觸發 popstate 事件,其他是否觸發問題你可以繼續嘗試
3. 簡單的實現與封裝
易懂的封裝:
function Router() { this.routes = {}; window.addEventListener('load', this.resolve.bind(this), false); window.addEventListener('hashchange', this.resolve.bind(this), false); } Router.prototype.route = function(path, callback) { this.routes[path] = callback || function(){}; } Router.prototype.resolve = function() { this.curHash = location.hash.slice(1) || '/'; typeof this.routes[this.curHash] === 'function' && this.routes[this.curHash](); }
簡單的案例:
<ul> <li><a href="#blue">藍色</a></li> <li><a href="#yellow">黃色</a></li> </ul> <ul> <li><a href="#red">紅色</a></li> </ul>
var router = new Router(); router.route('blue', function(){ document.body.style.background = 'lightblue'; }); router.route('yellow', function(){ document.body.style.background = 'yellow'; }); router.route('red', function(){ document.body.style.background = 'red'; });
DEMO1: https://foreverz133.github.io/demos/single/router.html
DEMO2: https://foreverz133.github.io/demos/single/history.html
五、其他
1. 不是所有頁面都需要改變 url,因為它會牽扯到回退
2. 瀏覽器的回退在體驗上對前端是道比較難回答的題,比如回退兩頁,不返回登錄/支付等
3. 在轉場之間加上動畫,當然要完成這效果就得使用 click 和 transitionEnd 等事件了
4. 狀態控制,最便捷(並非最佳)的辦法是全局一個對象去保存這些狀態,每次進行判斷和初始化操作
5. 當然如果你會 ReactJS 等模塊化渲染的話,路由還可以更厲害
6. 還要比往常遇到更多優化上的問題,比如資源加載/數據更新/操作流暢度等
7. 梳理邏輯和確定狀態,這些前期的事遠比書寫更重要,不然你會被改死的,講真!
本文所提路由還太狹隘,畢竟路由是前后端都有的東西,url 也僅僅是指向某資源,所以它還會涵蓋處理數據/數據傳遞等更多方面
六、總結
單頁面應用(SPA)對前端的要求成倍增加,對開發者來說其實是好事,
有挑戰進度會更快,不過和后端/策划的契合度也要相應提高才行。