1. 前言
本小節(jié)我們將介紹 Vue 的動(dòng)態(tài)組件,以及緩存 keep-alive 的使用。包括動(dòng)態(tài)組件的使用方法,以及如何使用 keep-alive 實(shí)現(xiàn)組件的緩存效果。
2. 慕課解釋
動(dòng)態(tài)組件是讓多個(gè)組件使用同一個(gè)掛載點(diǎn),并動(dòng)態(tài)切換。動(dòng)態(tài)組件是 Vue 的一個(gè)高級(jí)用法,但其實(shí)它的使用非常簡(jiǎn)單。keep-alive 是 vue 的內(nèi)置組件,能在組件切換過程中將狀態(tài)保存在內(nèi)存中,防止重復(fù)渲染 DOM。
3. 動(dòng)態(tài)組件如何使用
通過使用保留的 <component>
元素,動(dòng)態(tài)地把組件名稱綁定到它的 is
特性,可以實(shí)現(xiàn)動(dòng)態(tài)組件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<component :is="currentView"></component>
<button @click="changeView('A')">切換到A</button>
<button @click="changeView('B')">切換到B</button>
<button @click="changeView('C')">切換到C</button>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('ComponentA', {
template: '<div> 組件 A </div>',
})
Vue.component('ComponentB', {
template: '<div> 組件 B </div>',
})
Vue.component('ComponentC', {
template: '<div> 組件 C </div>',
})
var vm = new Vue({
el: '#app',
data() {
return {
currentView: 'ComponentB'
}
},
methods: {
changeView(name) {
this.currentView = `Component${name}`
}
}
})
</script>
</html>
代碼解釋:
HTML 代碼第 2 行,我們使用動(dòng)態(tài)組件 component,將當(dāng)前需要展示的組件名通過變量 currentView 綁定到 component 的 is 屬性上。
HTML 代碼第 3-5 行,我們定義了三個(gè)按鈕,通過點(diǎn)擊按鈕切換 currentView 的值。
JS 代碼第 3-11 行,我們定義了組件 ComponentA、ComponentB、ComponentC。
最終的實(shí)現(xiàn)效果是:當(dāng)點(diǎn)擊按鈕的時(shí)候會(huì)動(dòng)態(tài)切換展示的組件。
4. keep-alive
keep-alive
是 Vue
提供的一個(gè)抽象組件,用來對(duì)組件進(jìn)行緩存,從而節(jié)省性能,由于是一個(gè)抽象組件,所以在頁面渲染完畢后不會(huì)被渲染成一個(gè) DOM 元素。被 keep-alive
緩存的組件只有在初次渲染時(shí)才會(huì)被創(chuàng)建,并且當(dāng)組件切換時(shí)不會(huì)被銷毀。
4.1. 基礎(chǔ)用法
keep-alive
的用法相對(duì)簡(jiǎn)單,直接使用 keep-alive
包裹需要緩存的組件即可:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<keep-alive>
<component :is="currentView"></component>
</keep-alive>
<button @click="changeView('A')">切換到A</button>
<button @click="changeView('B')">切換到B</button>
<button @click="changeView('C')">切換到C</button>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('ComponentA', {
template: '<div> 組件 A </div>',
created() {
console.log('組件A created')
}
})
Vue.component('ComponentB', {
template: '<div> 組件 B </div>',
created() {
console.log('組件B created')
}
})
Vue.component('ComponentC', {
template: '<div> 組件 C </div>',
created() {
console.log('組件C created')
}
})
var vm = new Vue({
el: '#app',
data() {
return {
currentView: 'ComponentB'
}
},
methods: {
changeView(name) {
this.currentView = `Component${name}`
}
}
})
</script>
</html>
代碼解釋:
HTML 代碼第 2-3 行,我們使用 keep-alive 包裹動(dòng)態(tài)組件 component,將當(dāng)前需要展示的組件名通過變量 currentView 綁定到 component 的 is 屬性上。
HTML 代碼第 5-7 行,我們定義了三個(gè)按鈕,通過點(diǎn)擊按鈕切換 currentView 的值。
JS 代碼第 3-29 行,我們定義了組件 ComponentA、ComponentB、ComponentC,分別定義了他們的 created 和 beforeDestroy 事件。
之前我們介紹過,keep-alive
緩存的組件只有在初次渲染時(shí)才會(huì)被創(chuàng)建。所以,我們通過修改 currentView 切換組件時(shí),組件的 beforeDestroy 事件不會(huì)觸發(fā)。若該組件是第一次渲染,會(huì)觸發(fā) created 事件,當(dāng)再次切換顯示該組件時(shí),created 事件不會(huì)再次觸發(fā)。
4.2. activated 和 deactivated 生命周期
activated 和 deactivated 和我們之前學(xué)習(xí)的生命周期函數(shù)一樣,也是組件的生命周期函數(shù)。不過, activated
和 deactivated
只在 <keep-alive>
內(nèi)的所有嵌套組件中觸發(fā)。activated
:進(jìn)入組件時(shí)觸發(fā)。deactivated
:退出組件時(shí)觸發(fā)。
示例代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<keep-alive>
<component :is="currentView"></component>
</keep-alive>
<button @click="changeView('A')">切換到A</button>
<button @click="changeView('B')">切換到B</button>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('ComponentA', {
template: '<div> 組件 A </div>',
activated() {
console.log('組件A 被添加')
},
deactivated() {
console.log('組件A 被移除')
}
})
Vue.component('ComponentB', {
template: '<div> 組件 B </div>',
activated() {
console.log('組件B 被添加')
},
deactivated() {
console.log('組件B 被移除')
}
})
var vm = new Vue({
el: '#app',
data() {
return {
currentView: 'ComponentB'
}
},
methods: {
changeView(name) {
this.currentView = `Component${name}`
}
}
})
</script>
</html>
代碼解釋:
JS 代碼中,我們定義了組件 ComponentA、ComponentB,并分別定義了他們的 activated 和 deactivated 事件函數(shù)。
HTML 代碼第 2-3 行,我們使用 keep-alive 包裹動(dòng)態(tài)組件 component,將當(dāng)前需要展示的組件名通過變量 currentView 綁定到 component 的 is 屬性上。
HTML 代碼第 5-6 行,我們定義了兩個(gè)按鈕,通過點(diǎn)擊按鈕切換 currentView 的值。當(dāng)我們切換組件顯示時(shí),可以看到這樣的打印信息:
1. ComponentA -> ComponentB 會(huì)打印出:組件A 被移除、組件B 被添加
2. ComponentB -> ComponentA 會(huì)打印出:組件B 被移除、組件A 被添加
TIPS: 注意,activated 和 deactivated 這兩個(gè)生命周期函數(shù)一定是要在使用了 keep-alive 組件后才會(huì)有的,否則不存在。
4.3. include 和 exclude
include
和 exclude
是 keep-alive 的兩個(gè)屬性,允許組件有條件地緩存。
include: 可以是字符串或正則表達(dá)式,用來表示只有名稱匹配的組件會(huì)被緩存。
exclude: 可以是字符串或正則表達(dá)式,用來表示名稱匹配的組件不會(huì)被緩存。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<keep-alive include="ComponentA,ComponentB">
<component :is="currentView"></component>
</keep-alive>
<button @click="changeView('A')">切換到A</button>
<button @click="changeView('B')">切換到B</button>
<button @click="changeView('C')">切換到C</button>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('ComponentA', {
template: '<div> 組件 A </div>',
created() {
console.log('組件A created')
},
activated() {
console.log('組件A 被添加')
},
deactivated() {
console.log('組件A 被移除')
}
})
Vue.component('ComponentB', {
template: '<div> 組件 B </div>',
created() {
console.log('組件B created')
},
activated() {
console.log('組件B 被添加')
},
deactivated() {
console.log('組件B 被移除')
}
})
Vue.component('ComponentC', {
template: '<div> 組件 C </div>',
created() {
console.log('組件C created')
},
activated() {
console.log('組件C 被添加')
},
deactivated() {
console.log('組件C 被移除')
}
})
var vm = new Vue({
el: '#app',
data() {
return {
currentView: 'ComponentB'
}
},
methods: {
changeView(name) {
this.currentView = `Component${name}`
}
}
})
</script>
</html>
代碼解釋:
HTML 代碼第 2-4 行,我們使用 keep-alive 包裹動(dòng)態(tài)組件 component。給 keep-alive 指定需要緩存組件 ComponentA,ComponentB。
在之前的小節(jié)我們了解到 keep-alive
緩存的組件只有在初次渲染時(shí)才會(huì)被創(chuàng)建。所以,在案例中,組件 ComponentA 和 ComponentB 的 created 函數(shù)只有在第一次組件被創(chuàng)建的時(shí)候才會(huì)觸發(fā),而 ComponentC 的 created 函數(shù)當(dāng)每次組件顯示的時(shí)候都會(huì)觸發(fā)。
exclude 示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<keep-alive exclude="ComponentA,ComponentB">
<component :is="currentView"></component>
</keep-alive>
<button @click="changeView('A')">切換到A</button>
<button @click="changeView('B')">切換到B</button>
<button @click="changeView('C')">切換到C</button>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('ComponentA', {
template: '<div> 組件 A </div>',
created() {
console.log('組件A created')
}
})
Vue.component('ComponentB', {
template: '<div> 組件 B </div>',
created() {
console.log('組件B created')
}
})
Vue.component('ComponentC', {
template: '<div> 組件 C </div>',
created() {
console.log('組件C created')
}
})
var vm = new Vue({
el: '#app',
data() {
return {
currentView: 'ComponentB'
}
},
methods: {
changeView(name) {
this.currentView = `Component${name}`
}
}
})
</script>
</html>
代碼解釋:
HTML 代碼第 2-4 行,我們使用 keep-alive 包裹動(dòng)態(tài)組件 component。給 keep-alive 指定不需要緩存組件 ComponentA,ComponentB。
5. 小結(jié)
本節(jié),我們帶大家學(xué)習(xí)了動(dòng)態(tài)組件和緩存組件在項(xiàng)目中的運(yùn)用。主要知識(shí)點(diǎn)有以下幾點(diǎn):
- 使用
<component :is="component-name"/>
的方式實(shí)現(xiàn)動(dòng)態(tài)組件; - 使用 keep-alive 實(shí)現(xiàn)組件的緩存;
- 使用 include 屬性指定需要緩存的組件;
- 使用 exclude 屬性指定不需要緩存的組件。