這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 一. keep-alive 的作用 二. keep-alive 的原理 三. keep-alive 的應用 四. keep-alive 的刷新 五. keep-alive 頁面緩存思路 一. keep-alive 的作用 首先引用官 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
前言
一. keep-alive 的作用
二. keep-alive 的原理
三. keep-alive 的應用
四. keep-alive 的刷新
五. keep-alive 頁面緩存思路
一. keep-alive 的作用
首先引用官網文檔介紹:keep-alive官方文檔
Vue 的 keep-alive為抽象組件,主要用於緩存內部組件數據狀態。可以將組件緩存起來併在需要時重新使用,而不是每次重新創建。這可以提高應用的性能和用戶體驗,特別是在需要頻繁切換組件時。
Props: include
- 字元串或正則表達式。只有名稱匹配的組件會被緩存。 exclude
- 字元串或正則表達式。任何名稱匹配的組件都不會被緩存。 max
- 數字。最多可以緩存多少組件實例。
用法:
<keep-alive>
包裹動態組件時,會緩存不活動的組件實例,而不是銷毀它們。和 <transition>
相似,<keep-alive>
是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出現在組件的父組件鏈中。
當組件在 <keep-alive>
內被切換,它的 activated 和 deactivated 這兩個生命周期鉤子函數將會被對應執行。
通常情況下,組件在銷毀時會釋放它所占用的資源,如 DOM 元素、監聽器、定時器等。而當組件需要重新使用時,需要重新創建這些資源,這會消耗額外的時間和性能。
使用
keep-alive
組件可以避免這種情況,它可以將組件緩存起來併在需要時直接使用,而不需要重新創建。這樣可以節省資源和提高性能,特別是對於那些需要頻繁切換的組件,比如 Tab 切換、路由切換等等。
另外,keep-alive
組件也提供了一些鉤子函數,可以用來在組件激活和失活時執行一些操作,比如更新數據、發送請求等等。這些鉤子函數包括:
-
activated
: 組件被激活時調用,可以用來更新數據等操作。 -
deactivated
: 組件被緩存時調用,可以用來清除數據等操作。
需要註意的是,
keep-alive
組件只能緩存有狀態組件,不能緩存無狀態組件(比如純展示組件)。此外,如果需要緩存多個組件,需要使用v-for
迴圈遍歷,而且每個緩存的組件必須有一個唯一的key
屬性。
總之,keep-alive
組件可以提高應用的性能和用戶體驗,特別是在需要頻繁切換組件時。但需要註意使用時的細節和限制。
二. keep-alive 的原理
keep-alive
組件的實現原理是將被緩存的組件實例存儲到一個緩存對象中,當需要重新渲染這個組件時,會從緩存中獲取到之前的實例,並將其重新掛載到 DOM 上。
從Vue的渲染看keep-alive的渲染
Vue的渲染是從圖中render階段開始的
但keep-alive的渲染是在patch階段(構建組件樹(虛擬DOM樹),並將VNode轉換成真正DOM節點的過程)
1、在首次載入被包裹組件時,由keep-alive.js中的render函數可知,vnode.componentInstance的值是undfined,keepAlive的值是true,因為keep-alive組件作為父組件,它的render函數會先於被包裹組件執行;那麼只執行到i(vnode,false),後面的邏輯不執行;
2、再次訪問被包裹組件時,vnode.componentInstance的值就是已經緩存的組件實例,那麼會執行insert(parentElm, vnode.elm, refElm)邏輯,這樣就直接把上一次的DOM插入到父元素中。
三. keep-alive 的應用
下麵是一個簡單的例子,演示瞭如何使用 keep-alive
組件緩存一個計數器組件:
<template> <div> <p>Count: {{ count }}</p> <button @click="increment">增加</button> <button @click="decrement">減少</button> <button @click="reset">重置</button> </div> </template> <script> export default { props: ['count'], methods: { increment() { this.$emit('increment') }, decrement() { this.$emit('decrement') }, reset() { this.$emit('reset') } } } </script>
父組件使用
<template> <div> <keep-alive> <counter :count="count" @increment="increment" @decrement="decrement" @reset="reset" /> </keep-alive> <button @click="increment">增加</button> <button @click="decrement">減少</button> <button @click="reset">重置</button> </div> </template> <script> import Counter from './Counter.vue' export default { components: { Counter }, data() { return { count: 0 } }, methods: { increment() { this.count++ }, decrement() { this.count-- }, reset() { this.count = 0 } } } </script>
在這個例子中,我們創建了一個計數器組件 Counter
,併在父組件中使用 keep-alive
組件來緩存它。我們還定義了一個 count
數據屬性,並將它傳遞給 Counter
組件作為一個 prop,用於展示當前的計數值。同時,我們還綁定了三個自定義事件 increment
、decrement
和 reset
,用於響應計數器的操作。
當我們點擊增加或減少按鈕時,Counter
組件的 count
屬性會發生變化,但由於它被包裹在 keep-alive
組件中,所以實際上並沒有被銷毀。當我們再次渲染 Counter
組件時,它會從緩存中獲取到之前的實例,並將其重新掛載到 DOM 上,這樣就能夠保留之前的狀態。 在上面的例子中,我們可以看到在 keep-alive
組件中只包含了一個 Counter
組件。但是,在實際應用中,我們可能需要緩存多個不同的組件,這時我們可以通過 include
和 exclude
屬性來指定要緩存或排除的組件。
例如,我們可以修改上面的例子,將 Counter
組件和另一個文本組件 Text
都緩存起來
<template> <div> <keep-alive :include="[Counter, Text]"> <component :is="currentComponent" :count="count" v-on:increment="increment" v-on:decrement="decrement" v-on:reset="reset" /> </keep-alive> <button @click="toggleComponent">切換</button> <button @click="increment">增加</button> <button @click="decrement">減少</button> <button @click="reset">重置</button> </div> </template> <script> import Counter from './Counter.vue' import Text from './Text.vue' export default { components: { Counter, Text }, data() { return { count: 0, currentComponent: 'Counter' } }, methods: { toggleComponent() { this.currentComponent = this.currentComponent === 'Counter' ? 'Text' : 'Counter' }, increment() { this.count++ }, decrement() { this.count-- }, reset() { this.count = 0 } } } </script>
在這個例子中,我們定義了一個 currentComponent
數據屬性,用於動態切換要渲染的組件。我們還使用了 component
元素來動態渲染不同的組件。
在 keep-alive
組件中,我們使用了 include
屬性來指定要緩存的組件。註意,這裡傳入的是一個數組,可以包含多個組件。
同時,我們還可以使用 exclude
屬性來排除某些組件不進行緩存。例如,我們可以將 Text
組件排除在緩存之外,如下所示:
<keep-alive :include="[Counter]" :exclude="[Text]"> <!-- 緩存 Counter 組件,排除 Text 組件 --> </keep-alive>
總之,
keep-alive
組件的作用是緩存動態組件或者組件的狀態,避免重覆渲染和銷毀組件,從而提高應用的性能。在實際應用中,我們可以通過指定要緩存或排除的組件來靈活地控制組件的緩存策略,以滿足不同的需求。
四. keep-alive 如何刷新
當使用 keep-alive
組件緩存一個組件時,如果需要在組件被緩存時執行一些操作,可以使用 activated
鉤子函數,在組件被激活(被緩存並且被展示)時觸發。如果需要在組件被緩存時清除一些數據或狀態,可以使用 deactivated
鉤子函數,在組件被停用(被緩存但不被展示)時觸發。
如果需要強制重新渲染被緩存的組件,可以使用 this.$forceUpdate()
方法。在被緩存的組件中,可以將這個方法綁定到一個按鈕上,當按鈕被點擊時,被緩存的組件會強制重新渲染。
需要註意的是,使用 this.$forceUpdate()
方法會重新渲染整個組件,包括不在 keep-alive
組件中的部分,因此需要謹慎使用,以免影響應用的性能。
除了使用
this.$forceUpdate()
方法強制重新渲染組件外,還可以使用include
和exclude
屬性來控制哪些組件應該被緩存或不被緩存。當我們需要更新一個被緩存的組件時,可以將它從緩存中排除,併在需要更新時再重新包含到緩存中。這樣可以避免無謂的重覆渲染,提高應用的性能。
綜上所述,我們可以通過使用 activated
和 deactivated
鉤子函數、this.$forceUpdate()
方法以及 include
和 exclude
屬性來控制被緩存的組件的刷新策略,以滿足不同的需求。
五. keep-alive 頁面緩存思路
功能需求描述:
- 頁面前進刷新,後退不刷新
- 動態配置可緩存的頁面
- 手動刷新已緩存的頁面
實現思路:動態include
配置緩存組件,路由攔截判斷當前跳轉路由是否配置可緩存
<template> <keep-alive :include="cachedViews" :exclude="excludeViews"> <router-view></router-view> </keep-alive> </template>
動態操作include綁定值store狀態管理:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { cachedViews: [], excludeViews: [] }, mutations: { ADD_CACHED_VIEW: (state, payload) => { if (state.cachedViews.includes(payload)) return state.cachedViews.push(payload) }, DEL_CACHED_VIEW: (state, payload) => { const index = state.cachedViews.indexOf(payload) index > -1 && state.cachedViews.splice(index, 1) } }, actions: { ADD_CACHED_VIEW({ commit, }, payload) { commit('ADD_CACHED_VIEW', payload) }, DEL_CACHED_VIEW({ commit, }, payload) { commit('DEL_CACHED_VIEW', payload) } } }) export default store
在路由攔截器中實現邏輯:
1.路由導航進入時,如果配置了緩存,則記錄狀態,並實現緩存頁面
2.路由離開時,刪除緩存標識
import store from '@/store' router.beforeEach((to, from, next) => { if (to.meta.keepAlive) { store.dispatch('ADD_CACHED_VIEW', to.name) } })
<script> export default { name: "B", beforeRouteLeave(to, from, next) { if (to.name != "C") { this.$store.dispatch('DEL_CACHED_VIEW', to.name) } next(); }, methods: { } }; </script>