記一次vue 的keep-alive踩坑之路

這個坑,從項目開始的時候就一直存在乏苦,在前期的時候還沒有影響到正常的流程,加之項目比較緊尤筐,就一直沒有花太多時間去管它汇荐。 可是在最近的業(yè)務(wù)中,這個問題已經(jīng)影響到了正常的流程盆繁,所以這周一直在尋找這個問題的解決方案掀淘。在經(jīng)歷了各種論壇和各種貼子之后,找到了我目前能找到的最合適的解決方法油昂,于是寫下了這篇文章革娄。

背景

用vue+cordova 做一個hybrid App,由于業(yè)務(wù)涉及的輸入數(shù)據(jù)比較多冕碟,可能一個表單會包含多個子頁面拦惋,這就要求在錄入數(shù)據(jù)的時候,進入子頁面之前需要將當前頁的數(shù)據(jù)緩存安寺,而在子頁面返回的時候厕妖,子頁面要銷毀。也就是說挑庶,app正常前進的時候言秸,頁面全部緩,返回的時候之前的頁面不需要刷新數(shù)據(jù)迎捺,直接讀取緩存數(shù)據(jù)举畸。
具體場景和這位仁兄一致: 另辟蹊徑:vue單頁面,多路由凳枝,前進刷新抄沮,后退不刷新

為了找到一個合適的解決方案,我將這個場景進行了盡可能的簡化范舀,做成了一個DEMO合是,用來模擬這個場景。

Demo是用Vue-cli生成的锭环,加上了簡單的幾個文件
項目結(jié)構(gòu)如下圖:


項目結(jié)構(gòu)圖

其中聪全,child目錄用來模擬子路由的,first/second是一級路由
具體路由文件如下:


router/index.js

最開始辅辩,什么都不處理难礼,只要上頁面上加上<router-link/> 是可以直接跳轉(zhuǎn)的娃圆,當然也不會緩存任何組件。

給子路由加上緩存

我的最終目的給項目中所有的模塊進行單獨緩存蛾茉,而一級頁面不緩存讼呢。所以用child來模擬一個模塊,first.vue 和 second.vue來模擬一級頁面
每個模塊(child)都有自己的入口谦炬,如child/index.vue悦屏,內(nèi)容如下:


child/index.vue

這樣可以將child下面所有的子路由進行緩存,可以用vue-devtool工具進行查看是否能夠成功緩存


vue-devtool

可以看到键思,child下面的list以及detail組件已經(jīng)緩存成功了础爬。
到這里,已經(jīng)實現(xiàn)了子路由的成功緩存吼鳞。

但是這樣會有一個問題:在頁面返回的時候看蚜,所以被緩存的組件,會一直被緩存赔桌,再次進入頁面的時候供炎,組件并不會自動刷新,所以造成從list 點擊不同的詳情頁的時候疾党,進入的都是同一個頁面音诫。
在vue-devtool中看到的現(xiàn)象如下圖:

緩存成功

當然,這種情況下也是有方法進行數(shù)據(jù)刷新的仿贬。因為所有被緩存的組件纽竣,再次進入的時候,會觸發(fā)其生命周期的activated方法(https://cn.vuejs.org/v2/api/#keep-alive)茧泪,可以在此進行強制數(shù)據(jù)刷新蜓氨。
顯然,這種方法不是我想要的队伟。

在返回之前銷毀當前實例

上面那種方法的問題在于:頁面返回的時候穴吹,后面的組件(實例)還被緩存著,所以vue并不會重新去刷新它們嗜侮。那么港令,如果在頁面返回之前將自己銷毀掉,vue也就找不到了锈颗,問題不就解決了么

正好顷霹,我項目用的ui框架是vonic https://github.com/wangdahoo/vonic/ ,在學(xué)習(xí)大神的源碼的時候,發(fā)現(xiàn)了這樣的一段代碼击吱,

vonic

這段代碼的作用有兩點:1淋淀、設(shè)置頁面切換的動畫(前進=》'forward',返回=>'back' )覆醇;2朵纷、設(shè)置頁面返回后的page position炭臭,也就是頁面滾動的位置。
實現(xiàn)原理大致如下:
用sessionStorage來存儲app打開過的路由袍辞,每當在路由跳轉(zhuǎn)之前鞋仍,先判斷將要去的路由toRoute是不是在sessionStorage里面存在:如果存在,那么頁面就是返回搅吁,將下一次路由切換的動畫換成back威创,并改變sessionStorage中的history=false;如果不存在似芝,那就是前進打開新的頁面那婉,同時將下一次路由切換的動畫改成forward,同時改變sessionStorage中的history=true党瓮,并記錄當前頁的scrollTop。

其實vue-router本身的路由和瀏覽器的history對象一樣盐类,對應(yīng)用程序來說寞奸,是不能直接操作的,這里作者用sessionStorage來模擬一個history在跳,從而實現(xiàn)某些功能枪萄,這種方法是值得點贊的。

到這里猫妙,我們已經(jīng)可以知道應(yīng)用曾經(jīng)打開過哪些頁面瓷翻,那我們在返回的時候是不是可以將某些頁面銷毀呢?答案是肯定的割坠。

我們要做的是齐帚,在頁面返回之前,也就是路由切換之前彼哼,要獲取需要銷毀的實例對象对妄。
上圖中有一個beforeEach,是vue-router提供的一個全局的鉤子函數(shù)敢朱,它可以監(jiān)聽到每一次路由的切換剪菱,但卻獲取不到任何vue的實例對象。
在看了幾遍vue-router的文檔之后https://router.vuejs.org/zh-cn/advanced/navigation-guards.html 拴签,我找到了一個組件內(nèi)的鉤子孝常,也就是官方文檔提到的導(dǎo)航守衛(wèi),如下圖所示:

導(dǎo)航守衛(wèi)

其中蚓哩,我們要用到的是這個beforeRouteLeave构灸,在將要離開組件對應(yīng)路由的時候會觸發(fā)這個鉤子。而最重要的是杖剪,這個鉤子可以獲取到當前的組件實例this冻押,所以我們可以在這個時候調(diào)用this.$destory()來銷毀當前實例驰贷,就能完美解決上面提到的問題。
而這個鉤子只能在組件內(nèi)使用洛巢,也就意味著我每個需要緩存的組件都要調(diào)用這個鉤子括袒,難道每個組件里面都去寫一遍這個鉤子函數(shù)嗎?

當然不用稿茉。

vue提供了全局的mixin方法锹锰,可以幫你在所有的實例里面加上這個鉤子。

由于我的demo中沒有用到vonic漓库,所以我只能參照大神的源碼恃慧,寫了一段,具體如下:


main.js

這樣渺蒿,便可以實現(xiàn)痢士,前進的時候緩存組件,返回的時候不刷新茂装,并將最后一個頁面銷毀怠蹂。

理論上,這個方案挺完美的少态。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末城侧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子彼妻,更是在濱河造成了極大的恐慌嫌佑,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侨歉,死亡現(xiàn)場離奇詭異屋摇,居然都是意外死亡,警方通過查閱死者的電腦和手機为肮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門摊册,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人颊艳,你說我怎么就攤上這事茅特。” “怎么了棋枕?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵白修,是天一觀的道長。 經(jīng)常有香客問我重斑,道長兵睛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮祖很,結(jié)果婚禮上笛丙,老公的妹妹穿的比我還像新娘。我一直安慰自己假颇,他們只是感情好胚鸯,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著笨鸡,像睡著了一般姜钳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上形耗,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天哥桥,我揣著相機與錄音,去河邊找鬼激涤。 笑死拟糕,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的倦踢。 我是一名探鬼主播已卸,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼硼一!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起梦抢,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤般贼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后奥吩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哼蛆,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年霞赫,在試婚紗的時候發(fā)現(xiàn)自己被綠了腮介。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡端衰,死狀恐怖叠洗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旅东,我是刑警寧澤灭抑,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站抵代,受9級特大地震影響腾节,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一案腺、第九天 我趴在偏房一處隱蔽的房頂上張望庆冕。 院中可真熱鬧,春花似錦劈榨、人聲如沸访递。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽力九。三九已至,卻和暖如春邑闺,著一層夾襖步出監(jiān)牢的瞬間跌前,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工陡舅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抵乓,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓靶衍,卻偏偏與公主長得像灾炭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子颅眶,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本文首發(fā)于TalkingCoder蜈出,一個有逼格的程序員社區(qū)。轉(zhuǎn)載請注明出處和作者涛酗。 寫在前面 本文為系列文章铡原,總共...
    Aresn閱讀 9,524評論 0 42
  • Vue 實例 屬性和方法 每個 Vue 實例都會代理其 data 對象里所有的屬性:var data = { a:...
    云之外閱讀 2,214評論 0 6
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容商叹。關(guān)于...
    云之外閱讀 5,050評論 0 29
  • 1.安裝 可以簡單地在頁面引入Vue.js作為獨立版本燕刻,Vue即被注冊為全局變量,可以在頁面使用了剖笙。 如果希望搭建...
    Awey閱讀 11,027評論 4 129
  • 坐在沙發(fā)一頭卵洗,右腿蜷在左腿下,胳膊支在扶手上弥咪,低矮的木質(zhì)扶手還墊了個抱枕过蹂,靠上去很舒服。已經(jīng)快下午三點了酪夷,今天你還...
    Lnrsyao閱讀 222評論 0 0