摘要:如何添加這個條件,判斷用戶是否刷新了頁面呢我們知道,當(dāng)使用后,只有第一次進入后會觸發(fā)鉤子函數(shù),再次進入就不再執(zhí)行了。
項目需求:目的:vue-cli構(gòu)建的vue單頁面應(yīng)用,某些特定的頁面,實現(xiàn)前進刷新,后退不刷新,類似app般的用戶體驗。
注: 此處的刷新特指當(dāng)進入此頁面時,觸發(fā)ajax請求,向服務(wù)器獲取數(shù)據(jù)。不刷新特指當(dāng)進入此頁面時,不觸發(fā)ajax請求,而是使用之前緩存的數(shù)據(jù),以便減少服務(wù)器請求,用戶體驗更流暢。
任何技術(shù)的探索,都來自項目的需求。之前經(jīng)手的一個項目是微信端商城,使用的是傳統(tǒng)的mvc模式,利用的是jq+js,因此對于商城的項目需求比較熟悉。目前在學(xué)習(xí)vue,練手一個商城,遇到之前經(jīng)常提及而無法很好解決的需求。有些頁面需要前進刷新,后退不刷新。比如,從商城的【首頁】-->【詳情頁】-->【訂單提交頁】,每次打開新頁面都需要獲取新數(shù)據(jù),但是按下返回鍵后,就不需要再獲取新數(shù)據(jù)了,而滾動條還保留在之前的位置。最常見的操作是從【首頁】-->【詳情頁】,然后在從【詳情頁】-->【首頁】,如此反復(fù)。
實例如圖:
前人栽樹,后人好乘涼。技術(shù)圈的分享一直都在蓬勃發(fā)展。遇到問題,我們可以盡情去搜索,去尋找大佬的足跡。針對上述需求,看到一個分享vue-router 之 keep-alive,比較符合我的需求,但是使用到我的項目上發(fā)現(xiàn),稍微有點不適合。此分享技術(shù)要點,比較適合兩個頁面之前的跳轉(zhuǎn),返回。而我的頁面是多個路由(2+)之間的跳轉(zhuǎn),返回。無奈,只能去自己探索發(fā)現(xiàn)。不過此技術(shù)要點給了我很好的啟發(fā),特此感謝作者。@ RoamIn
實現(xiàn)思路:注:demo中,index頁面包含三個鏈接導(dǎo)航。page1-->page2-->page3.依次前進,每次前進到一個新頁面都需要獲取數(shù)據(jù),而按下后退鍵后,從page3返回到page2,page2不再獲取新數(shù)據(jù),而是使用之前緩存的數(shù)據(jù)。從page2返回到page1時,page1不再獲取新數(shù)據(jù),而是使用之前的數(shù)據(jù)。所以,page1和page2需要緩存,page3不需要緩存。可以把page1想象成首頁,page2想象成詳情頁,page3想象成訂單提交頁。這樣方便理解。
利用keep-alive 緩存需要緩存的頁面
在app.vue中改寫router-view
在router/index.js中添加路由元信息,設(shè)置需要緩存的頁面
routes: [{ path: "/", name: "index", component: index, meta: { keepAlive: false, //此組件不需要被緩存 } }, { path: "/page1", name: "page1", component: page1, meta: { keepAlive: true, //此組件需要被緩存 } }, { path: "/page2", name: "page2", component: page2, meta: { keepAlive: true, // 此組件需要被緩存 } }, { path: "/page3", name: "page3", component: page3, meta: { keepAlive: false, // 此組件不需要被緩存 } } ]
鉤子函數(shù)的執(zhí)行順序
不使用keep-alive
beforeRouteEnter --> created --> mounted --> destroyed
使用keep-alive
beforeRouteEnter --> created --> mounted --> activated --> deactivated
再次進入緩存的頁面,只會觸發(fā)beforeRouteEnter -->activated --> deactivated 。created和mounted不會再執(zhí)行。我們可以利用不同的鉤子函數(shù),做不同的事。務(wù)必理解上述鉤子函數(shù)的執(zhí)行時機和執(zhí)行順序,本教程的核心就依賴于此鉤子函數(shù)
activated和deactivated是使用keep-alive后,vue中比較重要的兩個鉤子函數(shù),建議詳細(xì)了解下。
需緩存的頁面的寫法
注:demo中的page1和page2,這兩個頁面都需要緩存,思路一樣,以下以page1為例,page2不再贅述。
示例文件:components/page1.vue
data中初始化一個str字符串,存放從后臺獲取的數(shù)據(jù)
data() { return { msg: "我是第一個頁面", str: "" // 加載頁面后執(zhí)行獲取數(shù)據(jù)的方法,插入到此 }; }
methods中創(chuàng)建一個方法,模擬從后臺獲取數(shù)據(jù)
methods: { getData() { // getData方法,模擬從后臺請求數(shù)據(jù) this.str = "我是通過調(diào)用方法加載的數(shù)據(jù)。。。"; } }
修改router/index.js中的配置
每次進入頁面,我們都需要知曉是從哪個頁面進來的,用以判斷是否需要獲取數(shù)據(jù)。以這個page1頁面為例,當(dāng)我們知曉是從page2過來的,我們就可以認(rèn)為是用戶操作了返回鍵,這時page1頁面就不需要再獲取新數(shù)據(jù)了,使用之前緩存的數(shù)據(jù)就可以了。如果是從別的頁面過來的,我們就需要獲取數(shù)據(jù)。
我們可以通過beforeRouteEnter這個鉤子函數(shù)中的from參數(shù)判斷是從哪個頁面過來的,這個參數(shù)執(zhí)行時,組件實例還沒創(chuàng)建,所有不能在data中定義變量。我們可以在路由中定義一個變量,用來判斷。
在router/index.js的meta中添加isBack變量,默認(rèn)false
{ path: "/page1", name: "page1", component: page1, meta: { keepAlive: true, //此組件需要被緩存 isBack:false, //用于判斷上一個頁面是哪個 } }, { path: "/page2", name: "page2", component: page2, meta: { keepAlive: true, // 此組件需要被緩存 isBack:false, //用于判斷上一個頁面是哪個 } },
beforeRouteEnter中判斷是從哪個頁面過來的
判斷是從哪個路由過來的,如果是page2過來的,表明當(dāng)前頁面不需要刷新獲取新數(shù)據(jù),直接用之前緩存的數(shù)據(jù)即可
beforeRouteEnter(to, from, next) { // 路由導(dǎo)航鉤子,此時還不能獲取組件實例 `this`,所以無法在data中定義變量(利用vm除外) // 參考 https://router.vuejs.org/zh-cn/advanced/navigation-guards.html // 所以,利用路由元信息中的meta字段設(shè)置變量,方便在各個位置獲取。這就是為什么在meta中定義isBack // 參考 https://router.vuejs.org/zh-cn/advanced/meta.html if(from.name=="page2"){ to.meta.isBack=true; //判斷是從哪個路由過來的, //如果是page2過來的,表明當(dāng)前頁面不需要刷新獲取新數(shù)據(jù),直接用之前緩存的數(shù)據(jù)即可 } next(); },
activated中執(zhí)行g(shù)etData這個獲取數(shù)據(jù)的方法
因為這個頁面需要緩存。只有第一次進入時才會執(zhí)行created和mounted方法,再次進入就不執(zhí)行了。而activated每次進入都執(zhí)行,所以在這個鉤子函數(shù)中獲取數(shù)據(jù)。
activated() { if(!this.$route.meta.isBack){ // 如果isBack是false,表明需要獲取新數(shù)據(jù),否則就不再請求,直接使用緩存的數(shù)據(jù) this.getData(); } // 恢復(fù)成默認(rèn)的false,避免isBack一直是true,導(dǎo)致下次無法獲取數(shù)據(jù) this.$route.meta.isBack=false },
這樣就可以了?
當(dāng)這樣設(shè)置完畢后,你執(zhí)行起來,貌似是可以了。第一次進入page1,能獲取新數(shù)據(jù),從page2返回時,不再獲取新數(shù)據(jù)了,而是使用之前緩存的數(shù)據(jù)。但這樣還有一個問題,當(dāng)用戶從page1進入page2后,因為某種原因,手動刷新了page2的頁面。這時再返回到page1,發(fā)現(xiàn)之前緩存的數(shù)據(jù)丟失了,而且也沒有再重新獲取。所以我們還需要再添加一個判斷條件,當(dāng)用戶手動刷新頁面后,再返回時就需要重新獲取數(shù)據(jù)了。
如何添加這個條件,判斷用戶是否刷新了頁面呢?我們知道,當(dāng)使用keep-alive后,只有第一次進入后會觸發(fā)created鉤子函數(shù),再次進入就不再執(zhí)行了。當(dāng)用戶刷新了頁面,這個鉤子函數(shù)就會又執(zhí)行,所以,我們可以利用這個小技巧來做點文章。
data中定義變量isFirstEnter用來判斷是否第一次進入,或是否刷新了頁面,默認(rèn)false
data() { return { msg: "我是第一個頁面", str: "", // 加載頁面后執(zhí)行獲取數(shù)據(jù)的方法,插入到此 isFirstEnter:false // 是否第一次進入,默認(rèn)false }; },
created中把isFirstEnter變?yōu)閠rue,說明是第一次進入或刷新了頁面
created() { this.isFirstEnter=true; // 只有第一次進入或者刷新頁面后才會執(zhí)行此鉤子函數(shù) // 使用keep-alive后(2+次)進入不會再執(zhí)行此鉤子函數(shù) },
activated中增加判斷條件
activated() { if(!this.$route.meta.isBack || this.isFirstEnter){ // 如果isBack是false,表明需要獲取新數(shù)據(jù),否則就不再請求,直接使用緩存的數(shù)據(jù) // 如果isFirstEnter是true,表明是第一次進入此頁面或用戶刷新了頁面,需獲取新數(shù)據(jù) this.str=""http:// 把數(shù)據(jù)清空,可以稍微避免讓用戶看到之前緩存的數(shù)據(jù) this.getData(); } // 恢復(fù)成默認(rèn)的false,避免isBack一直是true,導(dǎo)致下次無法獲取數(shù)據(jù) this.$route.meta.isBack=false // 恢復(fù)成默認(rèn)的false,避免isBack一直是true,導(dǎo)致每次都獲取新數(shù)據(jù) this.isFirstEnter=false; },
這樣應(yīng)該就可以了
不需要緩存頁面的寫法
注:demo中的page3,這個頁面不需要緩存,該怎么寫就怎么寫,不需要做特別的設(shè)置。
其它設(shè)置:使用keep-alive后,可能有點小問題:第二個頁面可能繼承第一個頁面的滾動條的高度。(在我項目中遇到的)
比如:page1向下滾動后,再進入page2,這時page2的滾動條可能是之前的高度,可能不會在頂部。
解決方法一
每次離開記錄滾動條的高度,再次進入時根據(jù)項目需要再恢復(fù)之前的高度,或者置頂。
解決方法二(推薦)
router/index.js中添加如下代碼(如不理解,請看參考鏈接)
參考:HTML5 History 模式 滾動行為
mode: "history", scrollBehavior(to, from, savedPosition) { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } } }疑問點:
在此次demo練習(xí)中,打印了一下鉤子函數(shù)的執(zhí)行順序,發(fā)現(xiàn)一個疑問點(我對鉤子函數(shù)理解也很淺顯):
從page1進入page2時,先執(zhí)行了page2的beforeRouteEnter和created方法,然后才執(zhí)行page1的deactivated方法。
所以我把這兩個初始化設(shè)置,放在了activated里面,而沒有放在deactivated中
this.$route.meta.isBack=false; this.isFirstEnter=false;結(jié)束語:
為了解決這個前進刷新后退不刷新問題,讓我整整苦惱了一周時間,想了很多方法,也沒能解決。最后綜合各個大佬經(jīng)驗,試驗了很多次,才歸結(jié)出這個比較‘low’的方法。
目前,我也是vue小白,也在探索著前進,如果這個方法能解決你遇到的難題,我很高興。如果你認(rèn)為的確很low,求輕噴。
demo在下方的GitHub中,歡迎star。
也歡迎大家提供意見和建議,謝謝大家
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/89913.html
摘要:因為用戶不用在第一次進入應(yīng)用時下載所有代碼,用戶能更快的看到頁面并與之交互。譯高階函數(shù)利用和來編寫更易維護的代碼高階函數(shù)可以幫助你增強你的,讓你的代碼更具有聲明性。知道什么時候和怎樣使用高階函數(shù)是至關(guān)重要的。 Vue 折騰記 - (10) 給axios做個挺靠譜的封裝(報錯,鑒權(quán),跳轉(zhuǎn),攔截,提示) 稍微改改都能直接拿來用~~~喲吼吼,喲吼吼..... 如何無痛降低 if else 面...
摘要:并設(shè)置后退頁面數(shù)組。跳轉(zhuǎn)到或頁面,返回后回到緩存頁面,不刷新。由其他頁面進入則刷新。反正目前可以實現(xiàn)想要的效果。 關(guān)于填坑vue的前進刷新與后退不刷新,網(wǎng)上有很多方法,基本都是利用 keep-alive,但是試了好多種方法都不盡人意,后來有人提示說基于keepalive include,試驗了一下找到了些思路,暫時實驗可行,分享下共同探討學(xué)習(xí),也許不是最佳解決方案,但確實有效。這里需要...
摘要:執(zhí)行過程如下實現(xiàn)瀏覽器的前進后退第二個方法就是用兩個棧實現(xiàn)瀏覽器的前進后退功能。我們使用兩個棧,和,我們把首次瀏覽的頁面依次壓入棧,當(dāng)點擊后退按鈕時,再依次從棧中出棧,并將出棧的數(shù)據(jù)依次放入棧。 showImg(https://segmentfault.com/img/bVbtK6U?w=1280&h=910); 如果要你實現(xiàn)一個前端路由,應(yīng)該如何實現(xiàn)瀏覽器的前進與后退 ? 2. 問題...
showImg(https://segmentfault.com/img/bVbvOmp?w=1612&h=888); 隨著React Vue前端框架的興起,出現(xiàn)了Vue-router,react-router-dom等前端路由管理庫,利用他們構(gòu)建出來的單頁面應(yīng)用,也是越來越接近原生的體驗,再也不是以前的點擊標(biāo)簽跳轉(zhuǎn)頁面,刷新整個頁面了,那么他們的原理是什么呢? 優(yōu)質(zhì)gitHub開源練手項目: ...
閱讀 2506·2021-10-14 09:42
閱讀 1148·2021-09-22 15:09
閱讀 3552·2021-09-09 09:33
閱讀 3035·2021-09-07 09:59
閱讀 3648·2021-09-03 10:34
閱讀 3547·2021-07-26 22:01
閱讀 2829·2019-08-30 13:06
閱讀 1214·2019-08-30 10:48