摘要:首發(fā)前端路由實(shí)現(xiàn)了解新增了兩個(gè)和兩個(gè)都接收三個(gè)參數(shù)狀態(tài)對象一個(gè)對象,與用方法創(chuàng)建的新歷史記錄條目關(guān)聯(lián)??紤]到未來可能會(huì)對該方法進(jìn)行修改,傳一個(gè)空字符串會(huì)比較安全。該參數(shù)是可選的不指定的話則為文檔當(dāng)前。
首發(fā):前端路由實(shí)現(xiàn)(history)
了解HTML5 history新增了兩個(gè)API:history.pushState和history.replaceState
兩個(gè)API都接收三個(gè)參數(shù):
狀態(tài)對象(state object):一個(gè)JavaScript對象,與用pushState()方法創(chuàng)建的新歷史記錄條目關(guān)聯(lián)。無論何時(shí)用戶導(dǎo)航到新創(chuàng)建的狀態(tài),popstate事件都會(huì)被觸發(fā),并且事件對象的state屬性都包含歷史記錄條目的狀態(tài)對象的拷貝。
標(biāo)題(title):FireFox瀏覽器目前會(huì)忽略該參數(shù),雖然以后可能會(huì)用上。考慮到未來可能會(huì)對該方法進(jìn)行修改,傳一個(gè)空字符串會(huì)比較安全?;蛘?,你也可以傳入一個(gè)簡短的標(biāo)題,標(biāo)明將要進(jìn)入的狀態(tài)。
地址(URL): 新的歷史記錄條目的地址。瀏覽器不會(huì)在調(diào)用pushState()方法后加載該地址,但之后,可能會(huì)試圖加載,例如用戶重啟瀏覽器。新的URL不一定是絕對路徑;如果是相對路徑,它將以當(dāng)前URL為基準(zhǔn);傳入的URL與當(dāng)前URL應(yīng)該是同源的,否則,pushState()會(huì)拋出異常。該參數(shù)是可選的;不指定的話則為文檔當(dāng)前URL。
相同之處是兩個(gè) API 都會(huì)操作瀏覽器的歷史記錄,而不會(huì)引起頁面的刷新。
不同之處在于pushState會(huì)增加一條新的歷史記錄,而replaceState則會(huì)替換當(dāng)前的歷史記錄。
這里大家可以先F12試試,看看地址欄發(fā)生了什么變化
window.history.pushState(null, null, "hell"); window.history.pushState(null, null, "/hell"); window.history.pushState(null, null, "#/hello"); window.history.pushState(null, null, "?name=");
注意:這里的url不支持跨域,否則會(huì)拋出異常嘗試
index.html
前端路由實(shí)現(xiàn)
router.js
;(function(){ history.replaceState(null,null,"");//最開始的狀態(tài),采用replace直接替換 $("#router").html("nav1
") $("a").on("click",function(){ console.log(this.text) var text = this.text; $("#router").html(""+ text +"
") history.pushState(null,null,"#/"+text); }) })()
最簡單的示例,只能監(jiān)聽點(diǎn)擊事件,而瀏覽器中的后、前進(jìn)都不能監(jiān)聽地址欄的改變
router.js
狀態(tài)版 ;(function(){ var count = [0,0,0] $("#router").html("導(dǎo)航1:
"+count[0]+"導(dǎo)航2:
"+count[1]+"導(dǎo)航3:
"+count[2]) history.replaceState(count,null,"");//最開始的狀態(tài),采用replace直接替換 for(var i = 0 ; i<$("a").length; i++){ $("a")[i].index = i $("a").eq(i).on("click",function(){ console.log(this.index); var index = this.index; count[index]++; $("#router").html("導(dǎo)航1:
"+count[0]+"導(dǎo)航2:
"+count[1]+"導(dǎo)航3:
"+count[2]) history.pushState(count,null,"#/count"+count[index]);//之后的狀態(tài),需要進(jìn)行保存 }) } //監(jiān)聽history其他api導(dǎo)致地址欄url改變事件 window.addEventListener("popstate",function(e){ console.log(e.state); var state = e.state; $("#router").html("導(dǎo)航1:
"+state[0]+"導(dǎo)航2:
"+state[1]+"導(dǎo)航3:
"+state[2]) }) })()
popstate
當(dāng)活動(dòng)歷史記錄條目更改時(shí),將觸發(fā)popstate事件。如果被激活的歷史記錄條目是通過對history.pushState()的調(diào)用創(chuàng)建的,或者受到對history.replaceState()的調(diào)用的影響,popstate事件的state屬性包含歷史條目的狀態(tài)對象的副本。需要注意的是調(diào)用history.pushState()或history.replaceState()不會(huì)觸發(fā)popstate事件。只有在做出瀏覽器動(dòng)作時(shí),才會(huì)觸發(fā)該事件,如用戶點(diǎn)擊瀏覽器的回退按鈕(或者在Javascript代碼中調(diào)用history.back())
router.js
;(function(){ var url = "nav1"; history.replaceState(url,null,"");//最開始的狀態(tài),采用replace直接替換 $("#router").html(""+url+"
") $("a").on("click",function(){ console.log(this.text) url = this.text; $("#router").html(""+ url +"
") history.pushState(url,null,"#/"+url); }) window.addEventListener("popstate",function(e){ console.log(e.state); url = e.state $("#router").html(""+ url +"
") }); })()
兜兜轉(zhuǎn)轉(zhuǎn)我們算是回到了起點(diǎn),但是通過這張圖我們會(huì)發(fā)現(xiàn)頁面點(diǎn)擊刷新按鈕會(huì)有導(dǎo)航和內(nèi)容塊不一致的內(nèi)容,所以我們需要改進(jìn)他,并且監(jiān)聽load事件
改進(jìn)
;(function(){ $("a").on("click",function(){ console.log(this.text) url = this.text; $("#router").html(""+ url +"
") history.pushState(url,null,"#/"+url); }) window.addEventListener("popstate",function(e){ console.log(e.state); url = e.state $("#router").html(""+ url +"
") }); window.addEventListener("load",function(){ url = location.hash.slice(2) || "nav1"; history.replaceState(url,null,""); console.log(location.hash); $("#router").html(""+ url +"
"); }); })()
可以看到我們點(diǎn)擊刷新的時(shí)候?qū)Ш胶蛢?nèi)容區(qū)域一致了。
我們這里還是采用了ajax的load方法
router.js
;(function(){ var router = [ { "path":"index", "url":"./main.html" }, { "path":"news", "url":"./news.html" }, { "path":"about", "url":"./about.html" } ]; //改變頁面 function display_page(url){ $("#router").load(url) } $("a").on("click",function(){ var path = $(this).data("path"); console.log(path) for(var i in router){ if(router[i].path == path){ display_page(router[i].url); history.pushState(router[i].url,null,router[i].path); } } }) window.addEventListener("popstate",function(e){ var url = e.state; display_page(url); }); window.addEventListener("load",function(){ var start = location.href.lastIndexOf("/"); var path = location.hash.slice(start) || "index"; console.log(path) for(var i in router){//刷新 加載 console.log(1) if(router[i].path == path){ display_page(router[i].url); history.replaceState(router[i].url,null,path); break; } if(i == router.length-1){//重定向 display_page(router[0].url); history.replaceState(router[i].url,null,router[0].path); } } }); })()
可以看到基本是實(shí)現(xiàn)了history路由功能,但是這里有一個(gè)問題就是刷新后因?yàn)榈刂窓趗rl原因會(huì)報(bào)錯(cuò),也就是找不到這個(gè)頁面,這是由于刷新的時(shí)候是重載,重新向網(wǎng)站目錄查找文件,而我們當(dāng)前目錄并沒有這個(gè)文件資源所以導(dǎo)致報(bào)錯(cuò)。需要后臺(tái)攔截! 放棄!
折中
最后我還是屈服于#了
;(function(){ var router = [ { "path":"index", "url":"./main.html" }, { "path":"news", "url":"./news.html" }, { "path":"about", "url":"./about.html" } ]; //改變頁面 function display_page(url){ $("#router").load(url) } $("a").on("click",function(){ var path = $(this).data("path"); console.log(path) for(var i in router){ if(router[i].path == path){ display_page(router[i].url); history.pushState(router[i].url,null,"#/"+router[i].path); } } }) window.addEventListener("popstate",function(e){ var url = e.state; display_page(url); }); window.addEventListener("load",function(){ var path = location.hash.slice(2) || "/index"; console.log(path) for(var i in router){//刷新 加載 console.log(1) if(router[i].path == path){ display_page(router[i].url); history.replaceState(router[i].url,null,"#/" + path); break; } if(i == router.length-1){//重定向 display_page(router[0].url); history.replaceState(router[0].url,null,"#/" + router[0].path); } } }); })();
勉強(qiáng)的很呀
代碼: router(history)
演示: 演示地址
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/95584.html
摘要:而應(yīng)用便是基于前端路由實(shí)現(xiàn)的所以便有了前端路由。因?yàn)閮煞N模式都需要調(diào)用一個(gè)方法來實(shí)現(xiàn)不同路由內(nèi)容的刷新前端路由路由列表匹配當(dāng)前的路由匹配不到則使用配置內(nèi)容并渲染下面我們來實(shí)現(xiàn)兩種模式。 什么是路由? 路由這概念最開始是在后端出現(xiàn)的,在以前前后端不分離的時(shí)候,由后端來控制路由,服務(wù)器接收客戶端的請求,解析對應(yīng)的url路徑,并返回對應(yīng)的頁面/資源。 簡單的說 路由就是根據(jù)不同的url地...
摘要:如何實(shí)現(xiàn)前端路由要實(shí)現(xiàn)前端路由,需要解決兩個(gè)核心如何改變卻不引起頁面刷新如何檢測變化了下面分別使用和兩種實(shí)現(xiàn)方式回答上面的兩個(gè)核心問題。 原文鏈接:github.com/whinc/blog/… 在單頁應(yīng)用如此流行的今天,曾經(jīng)令人驚嘆的前端路由已經(jīng)成為各大框架的基礎(chǔ)標(biāo)配,每個(gè)框架都提供了強(qiáng)大的路由功能,導(dǎo)致路由實(shí)現(xiàn)變的復(fù)雜。想要搞懂路由內(nèi)部實(shí)現(xiàn)還是有些困難的,但是如果只想了解路由實(shí)現(xiàn)基本...
摘要:回調(diào)函數(shù)將在更新時(shí)觸發(fā),回調(diào)中的起到了新的的作用。注冊回調(diào)在中使用注冊的回調(diào)函數(shù),最終放在模塊的回調(diào)函數(shù)數(shù)組中。 原文地址:https://github.com/joeyguo/blog/issues/2 在單頁應(yīng)用上,前端路由并不陌生。很多前端框架也會(huì)有獨(dú)立開發(fā)或推薦配套使用的路由系統(tǒng)。那么,當(dāng)我們在談前端路由的時(shí)候,還可以談些什么?本文將簡要分析并實(shí)現(xiàn)一個(gè)的前端路由,并對 reac...
摘要:單頁面應(yīng)用利用了動(dòng)態(tài)變換網(wǎng)頁內(nèi)容避免了頁面重載路由則提供了瀏覽器地址變化網(wǎng)頁內(nèi)容也跟隨變化兩者結(jié)合起來則為我們提供了體驗(yàn)良好的單頁面應(yīng)用前端路由實(shí)現(xiàn)方式路由需要實(shí)現(xiàn)三個(gè)功能瀏覽器地址變化切換頁面點(diǎn)擊瀏覽器后退前進(jìn)按鈕,網(wǎng)頁內(nèi)容跟隨變化刷新瀏 單頁面應(yīng)用利用了JavaScript動(dòng)態(tài)變換網(wǎng)頁內(nèi)容,避免了頁面重載;路由則提供了瀏覽器地址變化,網(wǎng)頁內(nèi)容也跟隨變化,兩者結(jié)合起來則為我們提供了體...
摘要:開發(fā)中路由實(shí)現(xiàn)原理開發(fā)中路由實(shí)現(xiàn)原理服務(wù)端路由路由前端路由實(shí)現(xiàn)比較參考什么是路由根據(jù)不同的地址,展示不同的頁面或者更新頁面局部視圖服務(wù)端路由服務(wù)器端路由管理,常見的開發(fā)模式是前端根據(jù)的不同,使用發(fā)起異步請求,獲取不同的頁面資源,前端獲取資源 Web開發(fā)中路由實(shí)現(xiàn)原理 Web開發(fā)中路由實(shí)現(xiàn)原理 服務(wù)端路由 Hash路由 History 前端路由實(shí)現(xiàn)比較 參考: 什么是路由: 根據(jù)不同...
閱讀 2952·2021-10-14 09:50
閱讀 1266·2021-10-08 10:21
閱讀 3701·2021-10-08 10:16
閱讀 3107·2021-09-27 14:02
閱讀 3170·2021-09-23 11:21
閱讀 2213·2021-09-07 10:17
閱讀 435·2019-08-30 14:00
閱讀 2156·2019-08-29 17:26