摘要:場景再現(xiàn)眾所周知,有三種模式,一般的前端項目中會選擇模式進行開發(fā),最近做了一個運營活動就是基于的模式進行開發(fā)的。項目注冊了兩個路由抽象出來的入口頁面需要參數(shù),所以提供瀏覽器里輸入回車后,頁面自動增加一個變?yōu)椤?/p>
場景再現(xiàn)
眾所周知,vue-router有三種模式 :hash、html5、abstract , 一般的前端項目中會選擇hash模式進行開發(fā),最近做了一個運營活動就是基于vue-router的hash模式進行開發(fā)的。
項目注冊了兩個路由(抽象出來的Demo)
var router = new VueRouter({ routes: [{ name: "index", path: "", component: indexcomponent },{ name: "demo", path: "/demo", component: democomponent }] });
入口頁面需要參數(shù),所以提供URL:https://www.xxx.com?from=weixin, 瀏覽器里輸入URL回車后,頁面自動增加一個#/變?yōu)?b>https://www.xxx.com?from=weixin#/。
index頁面中一個按鈕點擊后跳轉(zhuǎn)demo,同時想攜帶index中獲取的參數(shù),看API選擇了如下方式,結(jié)果URL變成了:https://www.xxx.com?from=weixin#/test?userId=123
router.push({ path: "demo", query: { plan: "private" } })產(chǎn)生質(zhì)疑
URL有什么標準?(上面Demo頁面跳轉(zhuǎn)后URL看起來怪怪的)
vue-router是如何控制URL的?
質(zhì)疑探究 URL標準統(tǒng)一資源定位符(或稱統(tǒng)一資源定位器/定位地址、URL地址等,英語:Uniform Resource Locator,??s寫為URL)
標準格式:scheme:[//authority]path[?query][#fragment]
==例子==
下圖展示了兩個 URI 例子及它們的組成部分。
URL中的『?』『#』hierarchical part ┌───────────────────┴─────────────────────┐ authority path ┌───────────────┴───────────────┐┌───┴────┐abc://username:[email protected]:123/path/data?key=value&key2=value2#fragid1
└┬┘ └───────┬───────┘ └────┬────┘ └┬┘ └─────────┬─────────┘ └──┬──┘
scheme user information host port query fragmenturn:example:mammal:monotreme:echidna
└┬┘ └──────────────┬───────────────┘
scheme path
『?』
路徑與參數(shù)分隔符
瀏覽器只識別url中的第一個『?』,后面的會當做參數(shù)處理
『#』
『#』一般是頁面內(nèi)定位用的,如我們最熟悉不過的錨點定位
瀏覽器可以通過『onhashchange』監(jiān)聽hash的變化
http請求中不包含#
Request Headers中的Referer不包含#
改變#不觸發(fā)網(wǎng)頁重載
url中#后面出現(xiàn)的任何字符都會被截斷。(http://www.xxx.com/?color=#fff發(fā)出請求是:/color=)
改變#會改變history
window.location.hash讀取#值
URL讀取和操作URL讀取和操作涉及l(fā)ocation和history兩個對象,具體如下:
location API :
屬性
href = protocol + hostName + port + pathname + search + hash
host
origin
方法
assign
href
replace ,不記錄history
reload
history API:
方法
back()
forward()
go()
H5新增API
pushState()
replaceState()
popstate監(jiān)聽變化
vue-router路由實現(xiàn)淺析初始化router的時候,根據(jù)指定的mode選擇路由實現(xiàn),當然mode判斷有一定邏輯和兼容策略
switch (mode) { case "history": this.history = new HTML5History(this, options.base) break case "hash": this.history = new HashHistory(this, options.base, this.fallback) break case "abstract": this.history = new AbstractHistory(this, options.base) break default: if (process.env.NODE_ENV !== "production") { assert(false, `invalid mode: ${mode}`) } }
我們選擇hash模式進行深入分析,對應(yīng)HashHistory模塊,該模塊是history/hash.js實現(xiàn)的,當被調(diào)用的時候,對全局路由變化進行了監(jiān)聽
window.addEventListener(supportsPushState ? "popstate" : "hashchange", () => { ... })
同時hash.js中也實現(xiàn)了push等api方法的封裝,我們以push為例,根據(jù)源碼可以看出,它的實現(xiàn)是基于基類transitionTo的實現(xiàn),具體如下:
push (location: RawLocation, onComplete?: Function, onAbort?: Function) { const { current: fromRoute } = this this.transitionTo(location, route => { pushHash(route.fullPath) handleScroll(this.router, route, fromRoute, false) onComplete && onComplete(route) }, onAbort) }
既然調(diào)用了transitionTo那么來看它的實現(xiàn),獲取參數(shù)后調(diào)用confirmTransition
transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) { // 獲取URL中的參數(shù) const route = this.router.match(location, this.current) this.confirmTransition(route, () => { this.updateRoute(route) onComplete && onComplete(route) this.ensureURL() ... }) }
同時confirmTransition里實現(xiàn)了一個隊列,順序執(zhí)行,iterator通過后執(zhí)行next,進而志新pushHash(),實現(xiàn)頁面hash改變,最終實現(xiàn)了${base}#${path}的連接
function getUrl (path) { const href = window.location.href const i = href.indexOf("#") const base = i >= 0 ? href.slice(0, i) : href return `${base}#${path}` } function pushHash (path) { if (supportsPushState) { pushState(getUrl(path)) } else { window.location.hash = path } }問題解決
https://www.xxx.com?from=weixin#/test?userId=123這個頁面看起來感覺怪,是因為這個連接中幾乎包含了所有的參數(shù),而且hash里面還有一個問號,一個URL中多個問號的不常見
vue-router也是基于基本的URL操作來進行URL切換的,在基本基礎(chǔ)上進行了封裝。里面很多思路還是應(yīng)該多學(xué)習(xí)借鑒的。比如實現(xiàn)的隊列、繼承的運用等
總結(jié)標準的URL應(yīng)該是 search + hash ,不要被當下各種框架欺騙,誤以參數(shù)應(yīng)該在hash后面拼接
URL中可以有多個問號,但為了便于理解,還是盡量避免這種寫法
避免上面尷尬問題的一個方法是 HTML5 Histroy 模式,感興趣的同學(xué)可以關(guān)注并實踐一下
了解原理,了解設(shè)計模式,可以借鑒到平時開發(fā)項目中
參考文檔https://github.com/vuejs/vue-...
https://developer.mozilla.org...
https://en.wikipedia.org/wiki...
https://www.cnblogs.com/qingg...
http://www.cnblogs.com/qinggu...
https://segmentfault.com/p/12...
https://segmentfault.com/a/11...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96825.html
摘要:場景再現(xiàn)眾所周知,有三種模式,一般的前端項目中會選擇模式進行開發(fā),最近做了一個運營活動就是基于的模式進行開發(fā)的。項目注冊了兩個路由抽象出來的入口頁面需要參數(shù),所以提供瀏覽器里輸入回車后,頁面自動增加一個變?yōu)椤? 場景再現(xiàn) 眾所周知,vue-router有三種模式 :hash、html5、abstract , 一般的前端項目中會選擇hash模式進行開發(fā),最近做了一個運營活動就是基于vue-...
摘要:起因今天用打包的時候發(fā)現(xiàn)不加壓縮居然比加上還要小,命令行分兩次輸入回車的時候是正常的。反復(fù)實驗多次,打印也正常。拐回頭看我們的代碼我們來對比一下對錯寫法一個小失誤,順便附上我的翻版必究 起因 今天用webpack 打包的時候發(fā)現(xiàn) 不加 set NODE_ENV 壓縮 居然比加上 set NODE_ENV 還要小,命令行 分兩次輸入 set NODE_ENV=production (回...
摘要:最近開始移動端頁面的時候,被和坑了一把,于是決定對這兩個對象進行一個全面的剖析。但出于隱私方面的原因,對象不再允許腳本訪問已經(jīng)訪問過的實際。唯一保持使用的功能只有和方法。華為執(zhí)行完之后,我們發(fā)現(xiàn)不能回退了,是不是就跟實現(xiàn)同樣的效果了。 最近開始移動端頁面的時候,被window.location和window.history坑了一把,于是決定對這兩個對象進行一個全面的剖析。下面進行我們的...
摘要:和事件可用于處理。循環(huán)中的代碼塊將針對每個屬性執(zhí)行一次。返回值是被找到的值。是被視為節(jié)點樹的。將新元素作為父元素的最后一個子元素進行添加。返回指定的屬性值。把指定屬性設(shè)置或修改為指定的值。年齡必須是與之間的數(shù)字。 JS JS DOM onload 和 onunload 事件會在用戶進入或離開頁面時被觸發(fā)。onload 事件可用于檢測訪問者的瀏覽器類型和瀏覽器版本,并基于這些信息來加載網(wǎng)...
摘要:也就是說,在大多數(shù)情況下,他們只關(guān)注標簽中的,而忽略標簽周圍的上下文。就算對于大多數(shù)正常使用瀏覽器的用戶來說,人們也容易只被標簽中的內(nèi)容吸引,而忽略上下文??傊?,保持標簽中的關(guān)鍵字簡潔是非常重要的。 什么是標簽 官方定義是這樣的: The HTML element (or anchor element) creates a hyperlink to other web pages,...
閱讀 3807·2021-11-17 09:33
閱讀 2025·2021-10-26 09:51
閱讀 1541·2021-09-29 09:44
閱讀 1693·2019-08-30 15:55
閱讀 1457·2019-08-30 15:52
閱讀 2338·2019-08-30 15:43
閱讀 3444·2019-08-29 17:00
閱讀 2311·2019-08-29 16:23