使用this.$router.go(-1)遇到的一些問題及解決
前提條件
目前有這樣一個(gè)需求,在列表中,點(diǎn)擊列表的某個(gè)記錄,會(huì)直接進(jìn)入到A頁面假設(shè)為:http://localhost:8080/#/index/123,在A頁面內(nèi)部有以下元素:
(1)一個(gè)返回按鈕,通過this.$router.go(-1)返回,或者是window.close()直接關(guān)閉頁面。
(2)一個(gè)a標(biāo)簽的連接,點(diǎn)擊之后頁面跳轉(zhuǎn)到http://localhost:8080/#/index/234,其實(shí)還是當(dāng)前A頁面的路由,但是參數(shù)發(fā)生了變化,為了便于說明,這里我們假設(shè)為頁面B。
(3)一個(gè)button按鈕,點(diǎn)擊之后,彈出一個(gè)模態(tài)框,模態(tài)框內(nèi)內(nèi)是一個(gè)ifream,ifream加載的頁面為:http://localhost:8080/#/second,我們假設(shè)為C頁面。
需求描述
預(yù)期想實(shí)現(xiàn)的效果有三種場景,分別如下:
(1)通過列表進(jìn)入到頁面A,點(diǎn)擊button之后,頁面C在彈框中ifream里成功加載,然后關(guān)閉模態(tài)框,然后再點(diǎn)擊A頁面的返回按鈕,直接返回的到列表。
(2)在A頁面,點(diǎn)擊連接,可以在不刷新當(dāng)前頁面的情況下,進(jìn)入到頁面B(其實(shí)也A也同一個(gè)組件),然后重新渲染數(shù)據(jù),根據(jù)234查詢最新數(shù)據(jù)去加載和渲染頁面。
(3)在列表頁面,通過打開一個(gè)新的瀏覽器標(biāo)簽頁的方式進(jìn)入到頁面A,在頁面A中點(diǎn)擊a標(biāo)簽鏈接,跳轉(zhuǎn)到頁面B,然后在B頁面點(diǎn)擊返回按鈕回到A頁面,再在A頁面點(diǎn)擊返回按鈕,直接關(guān)閉當(dāng)前標(biāo)簽頁。
問題描述
1 無法返回到列表
在需求描述的第一種場景中,我們可以會(huì)通過給ifream直接賦值src的方式去實(shí)現(xiàn),你會(huì)驚奇的發(fā)現(xiàn),當(dāng)關(guān)閉模態(tài)框之后,點(diǎn)擊A頁面上的返回按鈕沒反應(yīng),需要再點(diǎn)擊一下才會(huì)返回到列表。
出現(xiàn)這種問題的主要原因還是在于通過ifream.src賦值,因?yàn)橛蛳嗤?,還是會(huì)忘window.history中插入一條歷史記錄,這是不可避免。
如何解決該問題呢?我們可以通過replace的方式來解決。
在給ifream的src賦值的時(shí)候,可以通過如下代碼:
<iframe ref="iframe"></iframe> this.$refs.iframe.contentWindow.location.replace("http://localhost:8080/#/second")
2 無法渲染的頁面
在需求描述的第二個(gè)場景中,如果我們在寫代碼的時(shí)候,直接給a標(biāo)簽的href賦值為http://localhot:8080/#/index/234,你會(huì)發(fā)現(xiàn),當(dāng)你點(diǎn)擊鏈接的時(shí)候,頁面沒有任何的反映。
這是因?yàn)閷τ趘ue來說,路由并沒有發(fā)生變化,僅僅是參數(shù)發(fā)生了變化,我們需要特殊處理。
可以通過router的beforeRouterEnter和beforeRouteUpdate兩個(gè)鉤子函數(shù)來解決。
如下:
beforeRouteEnter(to,from,next){ next(vm=>vm.init()); }, beforeRouteUpdate(to,from,next){ this.initWithObj(to); this.clickCount++; next(); },
- beforeRouterEnter是在路由發(fā)生變化進(jìn)入到頁面之前會(huì)走這個(gè)函數(shù),此時(shí)組件還沒有初始化,所以在這個(gè)方法內(nèi)部不能使用this,只能通過next中的vm對象進(jìn)行回調(diào),init()方法是組件中自己聲明的業(yè)務(wù)function,里面有axios查詢以及頁面渲染。注意:vm.init()調(diào)用的時(shí)機(jī)是在mountd之后。也就是說會(huì)在頁面加載完成后去調(diào)用。另外就是如果路由沒有發(fā)生變化,或者不是刷新頁面,這個(gè)函數(shù)只有走一次,也就是說,對于我們需求中的場景,當(dāng)路由參數(shù)發(fā)生變化的時(shí)候,不會(huì)重復(fù)走該方法。
- beforeRouteUpdate的應(yīng)用場景剛好對應(yīng)都場景2的需求,在路由不發(fā)生變化,但是參數(shù)發(fā)生變化的時(shí)候,會(huì)調(diào)用該函數(shù)。所以,我們在這個(gè)方法中,重新進(jìn)行數(shù)據(jù)的請求和加載,可以看到使用的是initWithObj這個(gè)業(yè)務(wù)方法,傳入的是to這個(gè)對象,主要是為了獲取變化后的參數(shù),重新請求后端接口刷新數(shù)據(jù)的。這里注意:不管是通過$router.go(-1)【對于路由發(fā)生變化的返回后頁面會(huì)重新刷新】 還是$router.back()【頁面不會(huì)刷新,走的緩存】,只要路由的參數(shù)發(fā)生變化了都會(huì)觸發(fā)該方法。
3 無法關(guān)閉的新頁簽
對于第三種需求場景,我們需要在A頁面的返回按鈕里面做一些業(yè)務(wù)邏輯處理,就是需要知道當(dāng)前頁面是否有history,有的話,可以返回,沒有的話,就直接關(guān)閉頁面。
查了一些博客和資料,不少人提到可以通過window.history.length來判斷,這是一個(gè)誤區(qū),history.length只會(huì)增加,不會(huì)減少,所以你無法得知是不是已經(jīng)到了最后一個(gè)頁面了,也就無法得知是否要關(guān)閉頁面。
還有一些博客提到,可以通過使用document.referrer來判斷,代碼如下:
if(document.referrer){ //可以繼續(xù)后退 this.$router.go(-1); }else{ //不可以后退 window.close(); }
首先,這種寫法是不行的,因?yàn)閐ocument.referrer如果為空,就一直為空,他是在什么時(shí)候?yàn)榭漳兀?/p>
就是我們直接打開一個(gè)新的瀏覽頁標(biāo)簽去渲染A頁面時(shí),document.referrer為空,即便我們在A頁面點(diǎn)擊鏈接跳轉(zhuǎn)到B頁面了,document.referrer還是為空。
所以按照如上代碼寫的時(shí)候,點(diǎn)擊鏈接后B頁面渲染,再點(diǎn)擊返回按鈕,直接關(guān)閉頁簽了,回不到A頁面了。
而且如果按照如上的寫法,我們通過列表直接跳轉(zhuǎn)到A頁面的場景下,點(diǎn)擊返回按鈕,也永遠(yuǎn)無法返回,因?yàn)樗叩氖窍旅娴膚indow.close().
如何兼顧頁簽方式打開和列表直接跳轉(zhuǎn)情況下的返回或者關(guān)閉頁面呢?
有沒有一種方法可以知道當(dāng)前通過this.$router.go(-1)是否還有頁面可以繼續(xù)返回呢?
答案是:沒有。 我們只能根據(jù)業(yè)務(wù)場景自己去做處理。
下面看如下一段代碼:
if(document.referrer || window.frames.length != parent.frames.length){ //可以繼續(xù)后退 this.$router.go(-1); }else{ //沒有父頁面 if(this.clickCount>0){ this.clickCount=-1; this.$router.back(); }else{ window.close() } }
這里有一個(gè)參數(shù)clickCount,在組件的data中定義,默認(rèn)為0。 他的主要作用是在新瀏覽器頁簽加載A頁面時(shí),判斷是否存在參數(shù)變化情況下的頁面“跳轉(zhuǎn)”,并實(shí)現(xiàn)路由的返回的。
總結(jié)
行文至此,三種需求以及場景都可以解決了。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue點(diǎn)擊頁面空白處實(shí)現(xiàn)保存功能
這篇文章主要介紹了vue點(diǎn)擊頁面空白處實(shí)現(xiàn)保存功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11vue3+vite多項(xiàng)目多模塊打包(基于vite-plugin-html插件)
這篇文章主要給大家介紹了關(guān)于vue3+vite基于vite-plugin-html插件實(shí)現(xiàn)多項(xiàng)目多模塊打包的相關(guān)資料,現(xiàn)在很多小伙伴都已經(jīng)使用Vite+Vue3開發(fā)項(xiàng)目了,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07手把手教你vue實(shí)現(xiàn)動(dòng)態(tài)路由
動(dòng)態(tài)路由可以根據(jù)不同用戶登錄獲取不一樣的路由層級,可隨時(shí)調(diào)配路由,下面這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)動(dòng)態(tài)路由的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07關(guān)于vue中watch檢測到不到對象屬性的變化的解決方法
本篇文章主要介紹了關(guān)于vue中watch檢測到不到對象屬性的變化的解決方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02Vuex2.0+Vue2.0構(gòu)建備忘錄應(yīng)用實(shí)踐
這篇文章主要為大家詳細(xì)介紹了Vuex2.0+Vue2.0構(gòu)建備忘錄應(yīng)用實(shí)踐,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Vue3解決Mockjs引入后并訪問404(Not Found) 的頁面報(bào)錯(cuò)問題
mock.js:是一款模擬數(shù)據(jù)生成器,可以生成隨機(jī)數(shù)據(jù),攔截 Ajax 請求,使用mockjs模擬后端接口,可隨機(jī)生成所需數(shù)據(jù),模擬對數(shù)據(jù)的增刪改查,本文給大家介紹了Vue3解決Mockjs引入后并訪問404(Not Found) 的頁面報(bào)錯(cuò)問題,需要的朋友可以參考下2025-04-04vue使用smooth-signature實(shí)現(xiàn)移動(dòng)端橫豎屏電子簽字
這篇文章主要為大家介紹了vue使用smooth-signature實(shí)現(xiàn)移動(dòng)端橫豎屏電子簽字示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10