A. 在Vue中如何緩存頁面
在Vue中經常會遇到需要緩存頁面的情況,如果不對Vue進行處理,那麼Vue默認是不會緩存頁面的。例如從菜譜列表界面進入到菜譜的詳情頁後,再從菜譜詳情頁中返回到菜譜列表頁面中時,菜譜列表是不需要進行刷新的,一個是增加了不必要的網路請求,第二個是如推薦菜譜後台是實時推薦的,每次請求的數據都不一定一樣的,這樣在用戶退出後甚至找不到之前的進入位置,造成了很不好的用戶體驗。類似的情況還有很多,那麼如何在Vue中控制頁面是否刷新呢?
設置方法
注意:以上兩種方法都可以對路由是否緩存進行設置,如果不論何種情況下都要緩存頁面,可以直接採用第一種方法,當然第二種情況同樣可以滿足情況;但是如果需要區分從不同頁面跳轉的情況來確定是否需要緩存的話,就需要用到第二種方法。
B. Vue組件傳值及頁面緩存問題
關於父組件的傳值類型和props更多的定義詳見官網 : vue官網
(2)子組件向父組件傳值
(3)通過 chlidren等方法調取用層級關系的組件內的數據和方法。
有很多時候根據業務需求要在同級組件或頁面間傳值,此處提供以下幾種方法作為參考:
(1)通過router-link進行跳轉
(2) this.$router.push()
此方法同樣是有path+query和name+params兩種方式:
總結:使用query,傳輸的值會在url後面以參數的形式顯示出來,可以刷新頁面,數據不變,但會是頁面路由過長;而params只要一刷新傳遞的參數就沒了。
(3)LocalStorage緩存傳值
注意:簡單的小項目可以這么做,如果項目很大,建議直接用vuex。
(4)通過Vuex進行傳值
(5)發布訂閱模式(也叫eventBus或事件匯流排)
在Vue的原型上定義一個變數eventBus,所有所有Vue的實例或組件都將共享這個eventBus,可以用eventBus來發布自定義事件,然後在組件中用eventBus訂閱自定義事件。就可以實現傳值。
詳細講解可看 鏈接
(6)Vue.observable
index.vue組件中觸發:
Vue中如何在切換組件過程中,將狀態保存到內存中,防止DOM重新渲染,通俗的講就是實現如何在一個頁面輸入部分數據後到了另一個頁面再返回該頁面,數據還在。
需求分析:Page1中錄入信息,頁面跳轉帶Page2,然後再返回Page1,之前Page1錄入的信息還存在。
現在更改需求為:
首頁是A頁面
A頁面跳轉到B,B頁面不需要緩存
B頁面跳轉到C,C頁面不需要被緩存
C頁面返回到B,B頁面需要緩存
B頁面返回到A,
A再次跳轉到B
(1)此時思路是在每個路由的beforeRouteLeave(to, from, next)鉤子中設置to.meta.keepAlive
beforeRouteLeave講解
PageA頁面:
PageB頁面:
(2)用eventBus解決此問題
需要注意的一點是發布訂閱第一次會無效,因為訂閱的組件還沒創建。解決方法就是首次進入pageB頁面時接收pageA頁面params里傳遞的參數。
C. 前端性能優化總結
gzip壓縮
gzip壓縮效率很高,可以達到70%的壓縮率
//npm i -D compression-webpack-plugin 安裝插件依賴
configureWebpack: config => {
const CompressionPlugin = require('compression-webpack-plugin')
config.plugins.push(new CompressionPlugin())
}
去掉console.log
生產環境中,不需要列印日誌。通過對webpack進行配置,打包時自動去掉console.log
//npm i -D terser-webpack-plugin
configureWebpack:config =>{
const TerserPlugin = require('terser-webpack-pulugin')
config.optimzation.minimizer.push(
new TerserPlugin({
extractComments:false,
terserOptions:{compress:{drop_console:true}} //插件配置項 移除console
})
)
}
去除SourceMap
代碼壓縮後進行調bug定位將非常困難,於是引入sourcemap記錄壓縮前後的位置信息記錄,當產生錯誤時直接定位到未壓縮前的位置,將大大的方便我們調試。
sourcemap附帶了很多信息,如果build需要生成sourcemap,將會大大降低build的速度,還會增加包的體積。
//vue 中
mole.exports = {
proctionSourceMap: false,
}
//react中
//打開webpack.config.prod.js
const shouldUseSourceMap = false
CDN
內容分發網路,它能夠實時地根據網路流量和各節點的連接、負載狀況以及到用戶的距離和響應時間等綜合信息將用戶的請求重新導向離用戶最近的服務節點上。其目的是使用戶可就近取得所需內容,解決 Internet網路擁擠的狀況,提高用戶訪問網站的響應速度。所以可以通過將資源部署在CDN上來提高響應速度,提高用戶體驗
預渲染
簡單來說,就是將瀏覽器解析JavaScript動態渲染的工作,在打包階段完成了(只構建了靜態數據)。換個說法,在構建過程中,webpack通過使用prerender-spa-plugin插件生成靜態結構的html
// 1、安裝prerender-spa-plugin
npm install prerender-spa-plugin --save-dev
// 2、安裝vue-meta-info
npm install vue-meta-info --save-dev
// 3、相關配置
// 預渲染配置:在webpack.prod.conf文件中加入
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
// 在 plugins 中加入
new PrerenderSPAPlugin({
// 生成文件的路徑,也可以與webpakc打包的一致。
// 下面這句話非常重要!!!
// 這個目錄只能有一級,如果目錄層次大於一級,在生成的時候不會有任何錯誤提示,在預渲染的時候只會卡著不動。
staticDir: path.join(__dirname, '../dist'),
// 對應自己的路由文件,比如a有參數,就需要寫成 /a/param1。
routes: ['/', '/first', '/second', '/third', '/fourth', '/userCenter/userFirst','/userCenter/userSecond','/userCenter/userThird'],
// 這個很重要,如果沒有配置這段,也不會進行預編譯
renderer: new Renderer({
inject: {
foo: 'bar'
},
// headless: false,
renderAfterDocumentEvent: 'render-event', // 在 main.js 中 document.dispatchEvent(new Event('render-event')),兩者的事件名稱要對應上。
args: ['--no-sandbox', '--disable-setuid-sandbox']
})
})
// 4、在main.js中
import MetaInfo from 'vue-meta-info'
new Vue({
el: '#app',
router,
components: { App },
template: '',
// 添加mounted,不然不會執行預編譯
mounted () {
document.dispatchEvent(new Event('render-event'))
}
})
注意:路由模式必須為 history ,如果不設置 history 模式,也能運行和生成文件,每個 index.html 文件的內容都會是一樣的
Service Worker
ServiceWorker 是運行在瀏覽器後台進程里的一段 JS,它可以做許多事情,比如攔截客戶端的請求、向客戶端發送消息、向伺服器發起請求等等,其中最重要的作用之一就是離線資源緩存。
ServiceWorker 擁有對緩存流程豐富靈活的控制能力,當頁面請求到 ServiceWorker 時,ServiceWorker 同時請求緩存和網路,把緩存的內容直接給用戶,而後覆蓋緩存
注意:需要HTTPS才能使用ServiceWorker
HTTP緩存
HTTP緩存一般分為兩類:強緩存(本地緩存)、協商緩存(304緩存)
普通刷新會啟用協商緩存
在地址欄輸入網址、通過鏈接引入資源等情況下,瀏覽器才啟用強緩存
強緩存(200)。本地緩存是最快速的一種緩存方式,只要資源還在緩存有效期內,瀏覽器就會直接在本地讀取,不會請求服務端。在chrome控制台的Network選項中可以看到該請求返回200的狀態碼,並且Size顯示from disk cache或from memory cache。強緩存可以通過設置兩種 HTTP Header 實現:Expires 和 Cache-Control。
協商緩存(304)。協商緩存,顧名思義是經過瀏覽器與伺服器之間協商過之後,在決定是否讀取本地緩存,如果伺服器通知瀏覽器可以讀取本地緩存,會返回304狀態碼,並且協商過程很簡單,只會發送頭信息,不會發送響應體。
協商緩存可以通過設置兩種 HTTP Header 實現:Last-Modified 和 ETag
首先在精確度上,Etag要優於Last-Modified
第二在性能上,Etag要遜於Last-Modified,畢竟Last-Modified只需要記錄時間,而Etag需要伺服器通過演算法來計算出一個hash值
第三在優先順序上,伺服器校驗優先考慮Etag
緩存優先順序:Service Worker -> Memory Cache(內存緩存) -> Disk Cache(硬碟緩存) -> Push Cache(推送緩存)
Push Cache 只在會話(session)中存在,會話結束就被釋放,而且緩存時間很短
HTTP2
HTTP2 四個新特性:
多路復用,無需多個TCP連接,因為其允許在單一的HTTP2連接上發起多重請求,因此可以不用依賴建立多個TCP連接。
二進制分幀,將所有要傳輸的消息採用二進制編碼,並且會將信息分割為更小的消息塊。
頭部壓縮,用HPACK技術壓縮頭部,減小報文大小
服務端推送,服務端可以在客戶端發起請求前發送數據,換句話說,服務端可以對客戶端的一個請求發送多個相應,並且資源可以正常緩存。
。。。。。。。。。。。。。
作者:MonkeySoft
篇幅有限更多請見擴展鏈接:http://www.mark-to-win.com/tutorial/50671.html
D. vue 緩存組件keep-alive
kee-alive 是 Vue 內置的一個組件, 可以使被包含的組件保留狀態,或避免重新渲染 。也就是所謂的組件緩存
keep-alive是一個抽象的組件,緩存的組件不會被mounted,為此提供activated和deactivated鉤子函數
在2.1.0 版本後keep-alive新加入了兩個屬性: include(包含的組件緩存生效) 與 exclude(排除的組件不緩存,優先順序大於include) 。
keep-alive可以接收3個屬性做為參數進行匹配對應的組件進行緩存:
include 包含的組件(可以為字元串,數組,以及正則表達式,只有匹配的組件會被緩存)
exclude 排除的組件(以為字元串,數組,以及正則表達式,任何匹配的組件都不會被緩存)
max 緩存組件的最大值(類型為字元或者數字,可以控制緩存組件的個數)
配合router使用
1.keep-alive 先匹配被包含組件的 name 欄位,如果 name 不可用,則匹配當前組件 components 配置中的注冊名稱。
2.keep-alive 不會在函數式組件中正常工作,因為它們沒有緩存實例。
3.當匹配條件同時在 include 與 exclude 存在時,以 exclude 優先順序最高(當前vue 2.4.2 version)。比如:包含於排除同時匹配到了組件A,那組件A不會被緩存。
4.包含在 keep-alive 中,但符合 exclude ,不會調用activated和 deactivated。
參考 https://juejin.cn/post/6844903918313406472
參考 https://www.imooc.com/article/302879
E. 如何解決h5、vue、uniapp等項目緩存問題
我們再開發web項目時,經常會遇到修改了css、js、html等靜態文件,並部署到伺服器之後。使用瀏覽器進行訪問的時候,發現並沒有什麼變化,這就是靜態緩存。我們應該如何處理靜態緩存呢?首先我們先了解什麼是靜態緩存。
html文件添加Expires時間
CDN是靜態緩存加速最典型的代表。CDN技術並不是一門新的技術,它是基於傳統 nginx、squid、varnish 等 web 緩存技術,結合 DNS 智能解析的靜態緩存加速技術。
方式二:
uniapp解決緩存的方式與vue一樣,但是uniapp兼容了很多平台,所以修改vue.config.js又不太一樣。如果uniapp根目錄下面沒有vue.config.js,則新建vue.config.js文件即可。
F. vue頁面緩存設置,動態設置頁面緩存
情景:A頁面—>B頁面—>C頁面,A頁面去B頁面期望B頁面不緩存,B頁面去C頁面時,期望B頁面可以被緩存。(實際場景可以是:A為首頁,B為列表頁,C為詳情頁,B滾動翻頁後,從C返回B,記錄滾動位置。)
通過路由訪問鉤子設置B頁面的keepAlive為true或者false。
離開路由後,判斷to.name是否是A的路由名,是的話設置為false,否則設置為true。注意B頁面的keepAlive要設置為true。
2.通過vuex結合路由的includes功能以及路由鉤子函數實現。(推薦,實現起來優雅)
3.聲明一個初始化頁面狀態,內部變數的函數,從a 頁面進入執行初始化函數,其餘情況不執行。視圖依賴數據驅動,所以可以實現效果。
G. vue 路由緩存
在寫一個移動端項目時遇到了一個問題,每一個tab欄所對應的頁面被封裝成一個組件進行
復用,結果會導致他們共用一個滾動條。解決辦法是給這個子組件加固定的高度(例如
height:100vh),同時加一個屬性overflow-y:auto,這樣就可以解決這個問題。之後發現每當進
入主頁中任意一篇文章再退出時,頁面重新載入渲染了,之前的文章消失了,所有在這里想到
了路由緩存。
先說一下keep-alive的屬性和用法。
Props :
用法 :
<keep-alive> 包裹動態組件時,會緩存不活動的組件實例,而不是銷毀它們。
<keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出現在組件的父組件鏈中。
當組件在 <keep-alive> 內被切換,它的 activated 和 deactivated 這兩個生命周期鉤子函數將會被對應執行。
(只有被<keep-alive>包裹的組件才具有這兩個鉤子函數)
其實不太建議使用include的,因為如果多個組件中都包括include中匹配到的組件,想單獨
的讓其中某個組件緩存是不太方便的。所以可以在分發路由時,在需要緩存的路由中把額外標
記的屬性寫在meta中,如圖1。
使用的時候可以在根組件中通過$route.meta.keepAlive取到該值,然後進行v-if判斷即可,如圖
2,這樣使用起來相對靈活一點。
使用keep-alive緩存路由後,已經解決了主要問題,但是有新的問題出現。緩存過的組件重
新被激活時不會記錄滾動條的狀態,默認置頂,所以應該監聽這個被復用的組件的onscroll事
件,動態記錄滾動條的位置狀態,然後重新賦值給scrollTop(如果還想優化最好給滾動事件來
一個防抖處理)。那麼問題來了,應該在何時重新賦值呢?上面用法中提到了當組件在<keep-
alive> 內被切換時會觸發activated這個鉤子函數,所以應在這里賦值。
H. vue 不是路由跳轉的頁面怎麼緩存
vue緩存主要四種方式:
使用vuex
存放在cookie中
存放在localStorage或者sessionStorage中
存放在路由集合中