詳解基于vue的移動(dòng)web app頁(yè)面緩存解決方案
現(xiàn)在移動(dòng)web app越來(lái)越熱門了,許多公司開始嘗試使用angular、react、vue等MVVM框架來(lái)開發(fā)單頁(yè)架構(gòu)的web app。但在開發(fā)web app時(shí),如果希望頁(yè)面的導(dǎo)航體驗(yàn)也接近原生應(yīng)用,那一般都會(huì)遇到這兩個(gè)問(wèn)題:
- 識(shí)別前進(jìn)后退行為
- 后退時(shí)恢復(fù)之前的頁(yè)面
筆者開發(fā)了一個(gè)基于vue與vue-router的導(dǎo)航庫(kù)vue-navigation,來(lái)幫助開發(fā)者來(lái)解決這些問(wèn)題,下面是問(wèn)題的解決思路。
識(shí)別前進(jìn)后退
先說(shuō)第一個(gè)問(wèn)題。和原生app不一樣,瀏覽器中主要有這幾個(gè)限制:
- 沒(méi)有提供前進(jìn)后退的事件
- 不允許開發(fā)者讀取瀏覽記錄
- 用戶可以手動(dòng)輸入地址,或使用瀏覽器提供的前進(jìn)后退來(lái)改變url
解決方案是自己維護(hù)一份瀏覽記錄,每次url改變時(shí),通過(guò)與記錄的瀏覽記錄作對(duì)比,從而判斷出前進(jìn)后退行為:
- url存在于瀏覽記錄中即為后退
- url不存在于瀏覽記錄中即為前進(jìn)
- url在瀏覽記錄的末端即為刷新
另外,應(yīng)用的路由路徑中可能允許相同的路由出現(xiàn)多次(例如A->B->A),所以給每個(gè)路由添加一個(gè)key值來(lái)區(qū)分相同路由的不同實(shí)例。
這個(gè)瀏覽記錄需要存儲(chǔ)在sessionStorage中,這樣用戶刷新后瀏覽記錄也可以恢復(fù)。
后退時(shí)恢復(fù)之前的頁(yè)面
識(shí)別出后退行為后,下一步就是像原生一樣恢復(fù)之前的頁(yè)面了。
一種方案是頁(yè)面繼續(xù)存儲(chǔ)在DOM中,添加樣式display: none來(lái)告訴瀏覽器不渲染該元素,但是緩存的頁(yè)面多了DOM就會(huì)變得很大,會(huì)影響頁(yè)面的性能,本文不討論這個(gè)方案。
另一種方案是將數(shù)據(jù)緩存到內(nèi)存中,開發(fā)者需要將頁(yè)面的數(shù)據(jù)存儲(chǔ)起來(lái),當(dāng)返回到該頁(yè)面時(shí),再根據(jù)數(shù)據(jù)將頁(yè)面恢復(fù)。但是這樣每個(gè)頁(yè)面存儲(chǔ)的數(shù)據(jù)不通,一般需要進(jìn)行額外的編碼,如果有一種更底層的方案能解決這個(gè)問(wèn)題,并且對(duì)開發(fā)者是透明的,就最好了,所以嘗試并開發(fā)了vue-navigation。
在vue-navigation 0.x版本的時(shí)候,借助了vue的keep-alive來(lái)緩存頁(yè)面,但是keep-alive是根據(jù)組件的name或tag來(lái)決定緩存的,所以帶來(lái)了很多限制。
通過(guò)拜讀keep-alive的源碼,了解到它的緩存機(jī)制后,就自己實(shí)現(xiàn)了一個(gè)管理緩存的組件,來(lái)靈活地緩存子組件,實(shí)現(xiàn)思路如下:
- 每次render時(shí),先取到子組件的vnode(vue的虛擬dom)
- 計(jì)算出vnode的key,把key值賦給vnode避免vue-router復(fù)用組件實(shí)例
- 根據(jù)key值判斷該節(jié)點(diǎn)是否已緩存
- 已緩存:將緩存的實(shí)例賦給componentInstance,這樣vue就會(huì)根據(jù)這個(gè)實(shí)例來(lái)恢復(fù)組件
- 未緩存:將vnode存儲(chǔ)到內(nèi)存中,下次返回到該頁(yè)面時(shí)可以從內(nèi)存中恢復(fù)
另外還需要添加一個(gè)清除緩存的邏輯,當(dāng)自己維護(hù)的瀏覽記錄變化時(shí),根據(jù)瀏覽記錄清除不需要的緩存(例如當(dāng)前的路由是:A->B->C,用戶從C直接返回到了A,那么B和C都需要從緩存中刪除)。
最后
雖然是基于vue來(lái)開發(fā)的,但是思路是不變的,使用其他框架也可以做到同樣的事情。
還是安利一下vue和vue-navigation。使用插件后,再將router-view放在navigation下就有緩存功能了。
main.js
import Vue from 'vue' import router from './router' // vue-router 實(shí)例 import Navigation from 'vue-navigation' Vue.use(Navigation, {router}) // 啟動(dòng)你的應(yīng)用...
App.vue
<template> <navigation> <router-view></router-view> </navigation> </template>
最后歡迎大家討論或提供更好的解決方案。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- vue移動(dòng)端項(xiàng)目中如何實(shí)現(xiàn)頁(yè)面緩存的示例代碼
- vue頁(yè)面跳轉(zhuǎn)實(shí)現(xiàn)頁(yè)面緩存操作
- Vue2.0 實(shí)現(xiàn)頁(yè)面緩存和不緩存的方式
- vue項(xiàng)目強(qiáng)制清除頁(yè)面緩存的例子
- vuex + keep-alive實(shí)現(xiàn)tab標(biāo)簽頁(yè)面緩存功能
- vue服務(wù)端渲染頁(yè)面緩存和組件緩存的實(shí)例詳解
- Vue項(xiàng)目全局配置頁(yè)面緩存之按需讀取緩存的實(shí)現(xiàn)詳解
- 詳解vue之頁(yè)面緩存問(wèn)題(基于2.0)
- vue實(shí)現(xiàn)頁(yè)面緩存功能
相關(guān)文章
vue-cli3 配置開發(fā)與測(cè)試環(huán)境詳解
這篇文章主要介紹了vue-cli3 配置開發(fā)與測(cè)試環(huán)境詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05vue3 component is 不顯示的問(wèn)題及解決
這篇文章主要介紹了vue3 component is 不顯示的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03vue中提示$index is not defined錯(cuò)誤的解決方式
這篇文章主要介紹了vue中提示$index is not defined錯(cuò)誤的解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09Vue3使用時(shí)應(yīng)避免的10個(gè)錯(cuò)誤總結(jié)
Vue?3已經(jīng)穩(wěn)定了相當(dāng)長(zhǎng)一段時(shí)間了。許多代碼庫(kù)都在生產(chǎn)環(huán)境中使用它,其他人最終都將不得不遷移到Vue?3。我現(xiàn)在有機(jī)會(huì)使用它并記錄了我的錯(cuò)誤,下面這些錯(cuò)誤你可能想要避免2023-03-03vue.js實(shí)現(xiàn)標(biāo)簽頁(yè)切換效果
這篇文章主要介紹了vue.js實(shí)現(xiàn)標(biāo)簽頁(yè)切換效果,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-06-06基于vue框架手寫一個(gè)notify插件實(shí)現(xiàn)通知功能的方法
這篇文章主要介紹了基于vue框架手寫一個(gè)notify插件實(shí)現(xiàn)通知功能的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03