? ? ? ? 各位客爺大家好,疫情已經(jīng)肆虐了我們大半年的時間了鉴吹,不知各位有沒有在這個非常時期逆流而上找到自己心儀的工作呢~
? ? ? ? 在下今天主要來和各位一起討論一下vue-router history模式的實(shí)現(xiàn)方法
? ? ? ? 一豆励,經(jīng)典案例
? ? ? ? 事情的起因還要追溯于近期的一次提測瞒渠,切換場景(一個真實(shí)的case,如果您只想get干貨可以越過人生分割線來忽略):
? ? ? ? ———————————————? 人生分割線? ? —————————————————
? ? ? ? 我司的后臺系統(tǒng)使用vue+vue-router這種技術(shù)棧來實(shí)現(xiàn)嫩痰,由于業(yè)務(wù)需求較多串纺,這些頁面也就多到左側(cè)菜單欄無法承載的地步纺棺,所以我們每個人可見的左側(cè)顯示菜單邪狞,都是通過一個權(quán)限系統(tǒng)配制而成的帆卓。
? ? ? ? 左側(cè)的菜單欄點(diǎn)擊鏈接之后跳轉(zhuǎn)方式是window.location.href鳞疲,這次我們重構(gòu)將之前的hash模式改為了history模式,但是問題來了:
? ? ? ? 由于之前系統(tǒng)一直是以hash模式url跳轉(zhuǎn)蠕蚜,所以后臺配置的路徑一直是hash試的全路徑尚洽,例如:
? ? ? ? ? ? ? ? http://XXX.com/#home
? ? ? ? ? ? ? ? http://XXX.com/#list
? ? ? ? 但是當(dāng)我們改為了history模式之后(http://XXX.com/list),問題出現(xiàn)了靶累,每一次頁面跳轉(zhuǎn)都造成了頁面刷新腺毫。
? ? ? ? 我在這個跳轉(zhuǎn)邏輯里發(fā)現(xiàn)其實(shí)之前其實(shí)是有history模式的兼容的癣疟,只要從后臺配置的路徑不是全url路徑,是一個path的話潮酒,那就會使用vue-router的push方法跳轉(zhuǎn)睛挚,于是這個問題算是解決了。但是當(dāng)我們組妹子嬌嬌問我為什么之前使用全路徑都OK的時候急黎,我只是回復(fù)了她一句因?yàn)橹笆莌ash模式扎狱,如果換位思考的話,我對這個回答并不滿意勃教,因此我想通過這篇博文整體解釋一下為什么之前使用hash模式可以,但是history會出現(xiàn)問題。
? ? ? ? ————————————————? 人生分割線? ? ————————————————
? ? ? ? 二印机,原理分析
? ? ? ? 終于要上干貨了,我們來針對這幾個問題一一分析:
? ? ? ? 1咒劲,為什么之前hash模式,菜單配置全路徑頁面跳轉(zhuǎn)不刷新蛔屹?
? ? ? ? ? ? 根據(jù)http協(xié)議所示,url中hash改變請求是不會發(fā)送到服務(wù)端的育叁,不管你怎么location跳轉(zhuǎn),或者url上直接加上hash值回車隐锭,他都一樣固執(zhí),就是不和服務(wù)器老大說。
? ? ? ? ? ? 但是我們的系統(tǒng)里又引入了vue-router樱溉,其中hashchange這個事件監(jiān)聽又監(jiān)聽到了hash的變化撩嚼,從而觸發(fā)了組件的更新,也就繪制出了相應(yīng)的頁面逻族。
? ? ? ? 2要拂,為什么換成history模式搏嗡,每次點(diǎn)擊菜單的導(dǎo)航都會頁面刷新?
? ? ? ? ? ? 首先我們來看一下一個正確的history模式下磅氨,首頁刷新到顯示的整體流程:
? ? ? ? ? ? ? ? 1悍赢,將這個完整的url發(fā)到服務(wù)器ng
? ? ? ? ? ? ? ? 2,ng需要配置用這個uri再指給給前端index.html(這里我插一句哈,為什么要這么做呢,因?yàn)楦緵]有任何一個服務(wù)器提供了這個url路由糕再,如果直接訪問的話就是404究抓,所以需要指回給前端绑嘹,讓前端自己去根據(jù)path來顯示)
? ? ? ? ? ? ? ? 3,此時ng將這個請求指向了前端index.html,index.html中開始加載js惕鼓,js中已有vue-router的代碼一膨,vue-router自動觸發(fā)了popstate這個事件价淌,在這個事件回調(diào)中括尸,繪制了這個path下對應(yīng)的頁面組件
? ? ? ? ? ? 接著我們再來看一下vue-router push方法的頁面跳轉(zhuǎn)流程:
? ? ? ? ? ? ? ? 1啦膜,vue-router調(diào)用push方法首先會使用pushstate變換頁面url(僅僅變化url雀摘,頁面不變)
? ? ? ? ? ? ? ? 2乘粒,緊接著根據(jù)push方法中傳入的params找到對應(yīng)的組件【頁面】
? ? ? ? ? ? ? ? 3轧铁,載入對應(yīng)頁面組件绑洛,跳轉(zhuǎn)完畢
? ? ? ? ? ? 【劃重點(diǎn)】vue-router的push跳轉(zhuǎn)或者replace跳轉(zhuǎn)是不需要請求服務(wù)器的绑蔫!
? ? ? ? ? ? 但是我們?nèi)绻褂脀indow.location.href來做這個頁面跳轉(zhuǎn)篓叶,就基本上和web1.0沒什么區(qū)別,一定會先請求到服務(wù)器,再由服務(wù)器下發(fā)資源匹摇,導(dǎo)致頁面刷新~
? ? ? ? ? ? 講到這里我想妹子和我的困惑也都迎刃而解了坡垫,最近也有面試過一些前端溉卓,簡歷上也都有寫搞過vue-router的history模式爆阶,配置ng之類的徒役,但是當(dāng)我問為什么配上ng就可以正常訪問了,或者說ng是怎么實(shí)現(xiàn)頁面正常訪問的,基本上都能刷下一大波养匈,在下認(rèn)為搞技術(shù)的話一定要有敬畏之心猬仁,做項(xiàng)目要嚴(yán)謹(jǐn)诈闺,不能淺嘗輒止#@$!^$#&%.....
? ? ? ? ? ? 如果各位還想聽在下聊聊vue-router中使用的pushState方法的話漓穿,請越過下面的漲芝士分割線僚饭,如果已經(jīng)對這部分了如指掌的話击罪,那么就祝您找到自己稱心的工作了
? ? ? ? ————————————————? 漲芝士分割線? ? ————————————————
? ? ? ? 三竣稽,知識點(diǎn)討論
? ? ? ? ? ? 在下剛開始用 vue-router 的時候就好奇岛宦,為什么$router跳轉(zhuǎn)頁面的時候api是push,這分明是一個數(shù)組的方法嘛~但是后來在下閱讀了vue-router的源碼,發(fā)現(xiàn)猶大是用了pushState來做純前端的頁面跳轉(zhuǎn),在下不禁拍了下大腿署咽,我*高招啊饱须。
? ? ? ? ? ? 這個pushState單純的做了一個url的變化督怜,并且在路由隊列里加上了這條新的url的記錄屉凯,所以如果您在page1頁面使用了pushState這個方法灌旧,頁面不會變化,只是瀏覽器地址欄會發(fā)生更新,且瀏覽器的回退按鈕變成了可點(diǎn)擊狀態(tài)!
? ? ? ? ? ? 所以啸蜜,猶大在使用pushState將url改變之前拇泣,先做了頁面組件的刷新债朵,也就模擬出了頁面跳轉(zhuǎn)的樣子。
? ? ? ? ? ? 那么,如果我刷新首頁蔽莱,又或者前進(jìn)后退仪糖,怎么再更新頁面組件呢?答案就是使用popstate來做事件監(jiān)聽劲室,當(dāng)用戶首次訪問,前進(jìn)或后退的時候确买,都會觸發(fā)popstate事件铛楣,再由popstate來做當(dāng)前頁,上一頁等頁面的記錄和繪制缩焦。
—————————————————? 漲芝士分割線? —————————————————
? ? ? ? 今天就聊到這了葱轩,最近疫情北京又變中高風(fēng)險地區(qū)了,本來和老婆打算去玩?zhèn)€迪士尼來慶祝下一周年,看來也泡湯了本谜。最近公司組織架構(gòu)調(diào)整偎窘,我們部門在風(fēng)波中也被撕扯分裂到了各個新項(xiàng)目組他托,之前一起并肩奮斗的小伙伴也走了一小半把篓,但是至少窖铡,我們還有張照片~