摘要:監(jiān)聽的變動省略其他代碼省略其他代碼這樣,我們就初步實現(xiàn)了一個路由,那么接下來,我們來看看路由怎么實現(xiàn)。
前言
用過現(xiàn)代前端框架的同學,對前端路由一定不陌生, vue, react, angular 都有自己的 router, 那么你對 router 的工作原理了解嗎?
如果還不了解, 那么請跟我一起來手寫一個簡單的前端路由, 順便了解一下.
hash模式
history模式
缺點:
hash:丑(地址欄要多一個#), 某些特殊場景有坑 ,如微信支付回調(diào)
history: 兼容性較差, 直接訪問會400 ,除非后端或者服務(wù)器有做處理
基本原理hash是基于 監(jiān)聽 hashchange 事件實現(xiàn)的,history 是基于 pushState 和 popState,
實現(xiàn)由于history兼容性較差,而且實現(xiàn)方式基本沒多大區(qū)別,本文就以hash模式來實現(xiàn),history的實現(xiàn)方式只實現(xiàn)不同的部分。
Document
以上就是hash模式的最簡單實現(xiàn),查看控制臺,可以看到不管是點擊跳轉(zhuǎn)按鈕,還是點擊瀏覽器的前進/后退按鈕,控制臺都會輸出當前頁面對應(yīng)的 "url",有了 "url",我們就可以對內(nèi)容做條件渲染了
我們在上面的代碼的基礎(chǔ)上,稍作修改一下,增加2個div,一個是login,一個是index
Document
這樣,我們就能根據(jù)不同的hash地址,顯示不同的內(nèi)容,是不是已經(jīng)有點路由的味道了呢?但是目前還無法傳參,傳參的方式有很多種,最常見最通俗的,應(yīng)該是query string 了吧? query string 其實很簡單,解析url即可。
// 監(jiān)聽hash的變動 window.addEventListener("hashchange", function (e) { let url = location.hash.slice(1) || "index" // 解析url let questionIndex = url.indexOf("?") let path, query if(questionIndex >= 0){ path = url.substr(0,questionIndex) let queryString = url.substr(questionIndex+1) let queryArray = queryString.split("&") let queryObject = {} queryArray.map(str => { let equalIndex = str.indexOf("=") if(equalIndex > 0) { let key = str.substr(0,equalIndex) let value = str.substr(equalIndex+1) queryObject[key] = value } }) query = queryObject } else { path = url query = {} } console.log("接收到的參數(shù)", query) setVisible(path) })
這樣,我們就能獲取到URL上傳遞的query string , 還順便解決了傳參會導致路由解析不正確的bug.
傳參其實還有個更簡單的方法,就是 設(shè)置一個全局變量 param,然后在需要傳值的時候,直接對param 賦值即可
// 設(shè)置一個全局變量 var param = {}
// 頁面跳轉(zhuǎn) // 這個多了個參數(shù) args function hashPush(url, args) { location.hash = "#" + url param = args }
由于是全局變量,所以可以在任意位置使用 param,不過這樣直接使用全局變量的方式,也有它的弱點,就是點擊返回按鈕的時候無法保存變量,而query string 因為是在 url 里面的,所以返回的時候,可以拿到上個頁面的 query string,
那我們有沒有辦法讓全局變量的方式也能保存上一個頁面的參數(shù)呢? 我們來稍微修改一下代碼
// 設(shè)置一個全局變量 var param = {}
// 頁面跳轉(zhuǎn) // 這個多了個參數(shù) args function hashPush(url, args) { location.hash = "#" + url // 如果有傳args參數(shù),就在 param 對象下建一個名字跟當前url一樣的對象,并把args賦值給它 if(args) { param[url] = args } }
那我們在 hashchange 的時候,可以根據(jù)url來定位該頁面的參數(shù)。
// 監(jiān)聽hash的變動 window.addEventListener("hashchange", function (e) { // 省略其他代碼 args = param[path] || {} // 省略其他代碼 })
這樣,我們就初步實現(xiàn)了一個hash路由,那么接下來,我們來看看history路由怎么實現(xiàn)。
history 模式history 模式主要依靠 調(diào)用 history.pushState() 方法 和 監(jiān)聽 popstate 事件。
history.pushState() 方法接收3個參數(shù):
要傳遞的數(shù)據(jù)(參數(shù))
給頁面設(shè)置的標題(兼容性差,幾乎沒用)
url
我們看看調(diào)用實例
history.pushState({id:1}, "我是頁面標題", url)
需要注意的是 pushState 的時候,并不會觸發(fā) popstate 事件,只有在前進后退的時候,才會觸發(fā),所以 pushState 之后,需要手動去設(shè)置頁面的相關(guān)狀態(tài)。如上面的例子,我們需要這樣做
history.pushState({id:1}, "我是頁面標題", url) setVisible(url)
然后監(jiān)聽 popstate 事件,捕獲 前進/后退
window.addEventListener("popstate",function (e) { // e.state 就是你 pushState 的時候,傳的第一個參數(shù) let state = e.state || {} let url = state.target.location.pathName // 根據(jù)參數(shù) 做一些其他操作 })最后
本文最終實現(xiàn)代碼已經(jīng)放在 github上,想要直接看效果的同學,可以上去直接copy,運行。
如果覺得本文對您有用,請給本文的github加個star,萬分感謝
另外,github上還有其他一些關(guān)于前端的教程和組件,有興趣的童鞋可以看看,你們的支持就是我最大的動力。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/95794.html
摘要:單頁面應(yīng)用利用了動態(tài)變換網(wǎng)頁內(nèi)容避免了頁面重載路由則提供了瀏覽器地址變化網(wǎng)頁內(nèi)容也跟隨變化兩者結(jié)合起來則為我們提供了體驗良好的單頁面應(yīng)用前端路由實現(xiàn)方式路由需要實現(xiàn)三個功能瀏覽器地址變化切換頁面點擊瀏覽器后退前進按鈕,網(wǎng)頁內(nèi)容跟隨變化刷新瀏 單頁面應(yīng)用利用了JavaScript動態(tài)變換網(wǎng)頁內(nèi)容,避免了頁面重載;路由則提供了瀏覽器地址變化,網(wǎng)頁內(nèi)容也跟隨變化,兩者結(jié)合起來則為我們提供了體...
摘要:但是實際上,回款管理和開票管理的組件文件也是加載了。所以下面引用按需加載來處理。是不是小很多了,然后和是按需加載的,就是需要的時候才加載。 1.前言 上篇文章(webpack+vue項目實戰(zhàn)(二,開發(fā)管理系統(tǒng)主頁面)),實現(xiàn)了,側(cè)邊欄的一個操作,點擊側(cè)邊欄的一些操作,最重要的就是路由的切換。看了上一篇的伙伴也不難發(fā)現(xiàn),除了點擊側(cè)邊欄‘首頁’之外,點擊其它的都是白色的一片。原因我想大家都...
摘要:說明一直想做一個基于的項目但是因為項目往往要涉及到后端的知識不會后端真的苦所以就沒有一直真正的動手去做一個項目。直到發(fā)現(xiàn)上有網(wǎng)易云音樂的才開始動手去做。僅僅完成了首頁登入,歌單,歌曲列表頁。 說明 一直想做一個基于VUE的項目,但是因為項目往往要涉及到后端的知識(不會后端真的苦),所以就沒有一直真正的動手去做一個項目。直到發(fā)現(xiàn)GitHub上有網(wǎng)易云音樂的api NeteaseCloud...
摘要:而更多的應(yīng)用采用的是簡單的同構(gòu)實現(xiàn)。請使用動態(tài)路由進行處理。后來用布署頻繁調(diào)試,發(fā)現(xiàn)自定義在上并不能用,看建議使用動態(tài)路由。如果要取消這種行為可以使用方法。利用動態(tài)實現(xiàn)代碼塊切片。如果使用的話,建議使用動態(tài)路由去做布署啦。 使用next.js結(jié)合GITHUB ISSUE實現(xiàn)博客。 起因 。。。。起因是因為在某網(wǎng)站看到有一些類似實現(xiàn)。打算自己也做個side-project。 習慣性的對自...
摘要:大潮來襲前端開發(fā)能做些什么去年谷歌和火狐針對提出了的標準,顧名思義,即的體驗方式,我們可以戴著頭顯享受沉浸式的網(wǎng)頁,新的標準讓我們可以使用語言來開發(fā)。 VR 大潮來襲 --- 前端開發(fā)能做些什么 去年谷歌和火狐針對 WebVR 提出了 WebVR API 的標準,顧名思義,WebVR 即 web + VR 的體驗方式,我們可以戴著頭顯享受沉浸式的網(wǎng)頁,新的 API 標準讓我們可以使用 ...
閱讀 2566·2021-11-22 09:34
閱讀 3547·2021-11-15 11:37
閱讀 2346·2021-09-13 10:37
閱讀 2108·2021-09-04 16:40
閱讀 1577·2021-09-02 15:40
閱讀 2461·2019-08-30 13:14
閱讀 3332·2019-08-29 13:42
閱讀 1907·2019-08-29 13:02