<keep-alive>
的作用是缓存一个元件的资料状态,即使它被切换掉,不再呈现在画面上时,它的资料状态依然会把存起来,并不会像一般元件那样被销毁。
另外,is
属性的作用是动态载入元件,实现切换元件的效果。最常见的用法是在<component />
透过 v-bind
使用is
属性来切换显示元件:<component :is="...">
。而 is
属性也可以用在 HTML 标签上。
以下会再作详细解说。
keep-alive
?常用情景包括:
<keep-alive>
<component />
</keep-alive>
keep-alive 是一个抽象元件,即是它不会被渲染成 DOM 节点挂载在画面上。而被 <keep-alive>
所包着的元件的资料状态会被缓存起来。
该元件在只会跑一次生命周期,之後只会跑 activated
和 deactivated
这两个生命周期,代替 mounted
和unmounted
。我们可以在元件里使用此两个 lifecycle hook:
activated() {
...
}
deactivated() {
...
}
<keep-alive>
接收 3 个 props,让我们更客制化指定要缓存什麽元件。
<keep-alive include="" exclude="" max="">
</keep-alive>
官方文件清楚说明每个 prop 的型别和作用:
详细语法就不在此说明,有需要可再查看官方文件。
谨记:如果使用 include 和 exclude props 来指定元件名称时,该元件需要有 name 属性才会生效。
使用 include 指定元件 a 需要被缓存:
<keep-alive>
<component include="a" />
</keep-alive>
该元件要有 name 属性:
export default {
name: 'a'
}
同样地, router-view
也是一个元件,一样可以被 keep-alive
包起来,把此 router-view 里的所有元件都缓存起来:
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
目前 Vue 已经不容许
<router-view>
直接写在<keep-alive>
或<transition>
里面,需要使用v-slot
。
如果只是要缓存指定的元件,做法有两种:
include
、exclude
。meta
属性,再在里面自定义属性,让我们在 router-view
做判断哪些元件要被缓存。Example.vue
export default {
name: 'example'
}
App.vue
<router-view v-slot="{ Component }">
<keep-alive include="example">
<component :is="Component" />
// 只有 Example 元件会被缓存
</keep-alive>
</router-view>
router/index.js
export default [
{
path: '/example',
component: Example,
meta: {
keepAlive: true
}
}
]
App.vue
<router-view v-if="!$route.meta?.keepAlive" />
<router-view v-slot="{ Component }">
<keep-alive>
<component v-if="$route.meta?.keepAlive" :is="Component" />
</keep-alive>
</router-view>
注意,目前 Vue 已经不容许 <router-view>
直接写在 <keep-alive>
或 <transition>
里面,因此以下写法会跳错:
<template>
<router-view v-if="!$route.meta.keepAlive" />
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
</router-view>
</keep-alive>
</template>
以下程序码示范了第二种方法,即是在路由里设定 meta (自定义属性)来判断是否要套用 keep-alive
。例子中的 A 元件,你输入的资料後再跳回 Home,之後再次进入 A 元件,会发现资料有被缓存。但 B 元件则不会被缓存。
https://codesandbox.io/s/router-view-yu-keep-alive-mbcbf?file=/src/router/index.js
以下会用一个多步骤式表单示范如何使用 keep-alive
以及 is
属性,做法是参考此文章提及的情景需求。
https://codesandbox.io/s/keep-alive-duo-bu-biao-dan-li-zi-21mfo?file=/src/App.vue:28-253
目前需求是:
App.vue
<component :is="`Step${currentStep}`"/>
import Step1 from "@/components/Step1.vue";
import Step2 from "@/components/Step2.vue";
import Step3 from "@/components/Step3.vue";
export default {
components: {
Step1,
Step2,
Step3,
},
data() {
return {
currentStep: 1,
};
}
}
在每个元件绑上所需的事件,用来传送资料回到父元件 App.vue。以 Step1 元件为例:
Step1.vue
<template>
<h1>Step 1</h1>
<div>
<label for="name">Name:</label>
<input v-model="name" type="text" id="name" />
</div>
<div>
<label for="age">Age:</label>
<input v-model="age" type="number" id="age" />
</div>
<button @click="next()">Next</button>
</template>
export default {
// 有 name 属性,keep-alive 的 include 才会有效
name: "Step1",
// 不接收父元件传来的 inputData prop
inheritAttrs: false,
data() {
return {
name: "",
age: 0,
};
},
methods: {
next() {
this.$emit("change-step", 2);
this.$emit("update-data", {
name: this.name,
age: this.age,
});
},
},
activated() {
console.log("Step 1 is activate!");
},
deactivated() {
console.log("Step 1 is deactivated!");
},
};
有些重点要注意:
activated
和 deactivated
此两个 lifecycle hook。inheritAttrs: false
。因为在 Step 2 元件里没有根节点,所以 Vue 不晓得要把父元件的所有属性传给 Step 2 里哪个节点,因此解决方法有两种,一是设定 inheritAttrs: false
,直接关掉接收父元件的属性(因为 Step 2 没有用到父元件传来的 props)。二是把 <template>
里所有内容都用一个 div
包起来(在 codesandbox 的示范 code 中会有详细注解解释)。'change-step'
此事件,触发父元件修改当前的 step。按目前的需求,即是说:
在 Step 1 时:
- 要缓存 Step 1
在 Step 2 时:
- 要缓存 Step 1, Step 2
在 Step 3 时:
- 同样要缓存 Step 1, Step 2,但不用缓存 Step 3
所以,当前 Step 的数值,以及它之前的页面是需要被缓存。因此,可以利用此特性,使用 computed 回传一个阵列:
computed: {
keepAliveComponents() {
let alive = [];
for (let i = 0; i < this.currentStep; i++) {
// Step 3 是确认页面,不用缓存
if (i === 2) return alive;
alive.push(`Step${i + 1}`);
}
return alive;
}
}
因此,每次切换元件,透过动态绑定 :include="keepAliveComponents"
,计算什麽元件需要被缓存:
App.vue
<keep-alive :include="keepAliveComponents">
<component
:is="`Step${currentStep}`"
:inputData="inputData"
@change-step="changeStep"
@update-data="updateData"
/>
</keep-alive>
keep-alive
会缓存一个元件的资料状态。is
属性经常会与 v-bind
一起使用,作用是动态切换元件。keep-alive
接收 3 个 props,包括 include、exclude、max,指定要缓存的元件或缓存元件数量。[Vue] 跟着 Vue 闯荡前端世界 - 13 使用 keep-alive 保留表单状态
vue-router 之 keep-alive
<<: 【Day9】AddInvitationFragment(上)
>>: Day09 React Props- Array.map()
今天再多来看看两个Vue的指令,v-cloak与v-pre v-cloak 使用v-cloak的原因...
昨天介绍了各种选择器,今天介绍伪类及伪元素样式设定,可以让画面有更多的样式变化,也减少html co...
在 Structural patterns 当中,最後要来谈的是外观模式。 外观模式提供我们一个简单...
昨天我们做到ImageView及TextField会根据Slider的左右滑动而改变颜色及数值,但是...
前一天我们介绍了用来资料处理最基本的pandas套件 那今天我们则是来谈一下不同的档案类型 我们都知...