使用this.$router.go(-1)遇到的一些問題及解決
前提條件
目前有這樣一個需求,在列表中,點擊列表的某個記錄,會直接進入到A頁面假設為:http://localhost:8080/#/index/123,在A頁面內部有以下元素:
(1)一個返回按鈕,通過this.$router.go(-1)返回,或者是window.close()直接關閉頁面。
(2)一個a標簽的連接,點擊之后頁面跳轉到http://localhost:8080/#/index/234,其實還是當前A頁面的路由,但是參數(shù)發(fā)生了變化,為了便于說明,這里我們假設為頁面B。
(3)一個button按鈕,點擊之后,彈出一個模態(tài)框,模態(tài)框內內是一個ifream,ifream加載的頁面為:http://localhost:8080/#/second,我們假設為C頁面。
需求描述
預期想實現(xiàn)的效果有三種場景,分別如下:
(1)通過列表進入到頁面A,點擊button之后,頁面C在彈框中ifream里成功加載,然后關閉模態(tài)框,然后再點擊A頁面的返回按鈕,直接返回的到列表。
(2)在A頁面,點擊連接,可以在不刷新當前頁面的情況下,進入到頁面B(其實也A也同一個組件),然后重新渲染數(shù)據(jù),根據(jù)234查詢最新數(shù)據(jù)去加載和渲染頁面。
(3)在列表頁面,通過打開一個新的瀏覽器標簽頁的方式進入到頁面A,在頁面A中點擊a標簽鏈接,跳轉到頁面B,然后在B頁面點擊返回按鈕回到A頁面,再在A頁面點擊返回按鈕,直接關閉當前標簽頁。
問題描述
1 無法返回到列表
在需求描述的第一種場景中,我們可以會通過給ifream直接賦值src的方式去實現(xiàn),你會驚奇的發(fā)現(xiàn),當關閉模態(tài)框之后,點擊A頁面上的返回按鈕沒反應,需要再點擊一下才會返回到列表。
出現(xiàn)這種問題的主要原因還是在于通過ifream.src賦值,因為域相同,還是會忘window.history中插入一條歷史記錄,這是不可避免。
如何解決該問題呢?我們可以通過replace的方式來解決。
在給ifream的src賦值的時候,可以通過如下代碼:
<iframe ref="iframe"></iframe>
this.$refs.iframe.contentWindow.location.replace("http://localhost:8080/#/second")2 無法渲染的頁面
在需求描述的第二個場景中,如果我們在寫代碼的時候,直接給a標簽的href賦值為http://localhot:8080/#/index/234,你會發(fā)現(xiàn),當你點擊鏈接的時候,頁面沒有任何的反映。
這是因為對于vue來說,路由并沒有發(fā)生變化,僅僅是參數(shù)發(fā)生了變化,我們需要特殊處理。
可以通過router的beforeRouterEnter和beforeRouteUpdate兩個鉤子函數(shù)來解決。
如下:
beforeRouteEnter(to,from,next){
next(vm=>vm.init());
},
beforeRouteUpdate(to,from,next){
this.initWithObj(to);
this.clickCount++;
next();
},- beforeRouterEnter是在路由發(fā)生變化進入到頁面之前會走這個函數(shù),此時組件還沒有初始化,所以在這個方法內部不能使用this,只能通過next中的vm對象進行回調,init()方法是組件中自己聲明的業(yè)務function,里面有axios查詢以及頁面渲染。注意:vm.init()調用的時機是在mountd之后。也就是說會在頁面加載完成后去調用。另外就是如果路由沒有發(fā)生變化,或者不是刷新頁面,這個函數(shù)只有走一次,也就是說,對于我們需求中的場景,當路由參數(shù)發(fā)生變化的時候,不會重復走該方法。
- beforeRouteUpdate的應用場景剛好對應都場景2的需求,在路由不發(fā)生變化,但是參數(shù)發(fā)生變化的時候,會調用該函數(shù)。所以,我們在這個方法中,重新進行數(shù)據(jù)的請求和加載,可以看到使用的是initWithObj這個業(yè)務方法,傳入的是to這個對象,主要是為了獲取變化后的參數(shù),重新請求后端接口刷新數(shù)據(jù)的。這里注意:不管是通過$router.go(-1)【對于路由發(fā)生變化的返回后頁面會重新刷新】 還是$router.back()【頁面不會刷新,走的緩存】,只要路由的參數(shù)發(fā)生變化了都會觸發(fā)該方法。
3 無法關閉的新頁簽
對于第三種需求場景,我們需要在A頁面的返回按鈕里面做一些業(yè)務邏輯處理,就是需要知道當前頁面是否有history,有的話,可以返回,沒有的話,就直接關閉頁面。
查了一些博客和資料,不少人提到可以通過window.history.length來判斷,這是一個誤區(qū),history.length只會增加,不會減少,所以你無法得知是不是已經到了最后一個頁面了,也就無法得知是否要關閉頁面。
還有一些博客提到,可以通過使用document.referrer來判斷,代碼如下:
if(document.referrer){
//可以繼續(xù)后退
this.$router.go(-1);
}else{
//不可以后退
window.close();
}首先,這種寫法是不行的,因為document.referrer如果為空,就一直為空,他是在什么時候為空呢?
就是我們直接打開一個新的瀏覽頁標簽去渲染A頁面時,document.referrer為空,即便我們在A頁面點擊鏈接跳轉到B頁面了,document.referrer還是為空。
所以按照如上代碼寫的時候,點擊鏈接后B頁面渲染,再點擊返回按鈕,直接關閉頁簽了,回不到A頁面了。
而且如果按照如上的寫法,我們通過列表直接跳轉到A頁面的場景下,點擊返回按鈕,也永遠無法返回,因為他走的是下面的window.close().
如何兼顧頁簽方式打開和列表直接跳轉情況下的返回或者關閉頁面呢?
有沒有一種方法可以知道當前通過this.$router.go(-1)是否還有頁面可以繼續(xù)返回呢?
答案是:沒有。 我們只能根據(jù)業(yè)務場景自己去做處理。
下面看如下一段代碼:
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()
}
}這里有一個參數(shù)clickCount,在組件的data中定義,默認為0。 他的主要作用是在新瀏覽器頁簽加載A頁面時,判斷是否存在參數(shù)變化情況下的頁面“跳轉”,并實現(xiàn)路由的返回的。
總結
行文至此,三種需求以及場景都可以解決了。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Element Table的row-class-name無效與動態(tài)高亮顯示選中行背景色
這篇文章主要介紹了Element Table的row-class-name無效與動態(tài)高亮顯示選中行背景色,本文詳細的介紹了解決方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11
mpvue小程序循環(huán)動畫開啟暫停的實現(xiàn)方法
這篇文章主要介紹了mpvue小程序循環(huán)動畫開啟暫停的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-05-05

