Vue動態組件
文章目錄
一.背景
Vue 中提供有一個內置的組件叫做 component 。這個組件就是動態組件。它需要設置 is 屬性。is 屬性的值就是需要渲染的組件的名字
動態組件在我們實際開發中是很有用的,比如我們要實現選項卡切換的操作,對應的選項卡內容是不同的組件,這時我們就可以考慮使用動態組件.
我們知道,動態渲染組件的方式還很多種,比如使用v-if判斷,v-show實現組件樣式的顯示與隱藏,但是呢,一般我們要考慮到性能的問題
1.v-if動態加載
v-if操作,如果我們有很多組件需要動態的加載,那麼每一個組件都要去判斷,如果成百上千個,那你的代碼裏基本上就全是v-if了,其實這還不算什麼,最主要的是v-if操作,一直從創建到銷燬,會有dom開銷,頻繁切換的話,性能肯定很大的問題
額外擴展一句:使用v-if和v-once配合使用,可以達到v-show的性能要求
實際上使用動態組件時,也會有性能開銷,畢竟動態組件的原理也是這樣,切換過程中,也是組件的創建到銷燬操作,不過動態組件可以通過keep-alive來實現狀態保持,也就是緩存
2.v-show動態加載
v-show操作,雖然減少了頻繁切換的性能開銷,但是v-show實際上的原理只是做樣式 的顯示與隱藏,也就是說,在最開始加載的時候會全部加載,如果組件不大,可以這麼做,但是如果組件很龐大的話,初始加載,那肯定也是不友好的
那這裏,Vue中就給我們提供了一個內置組件:component也就是動態組件,可以解決這些問題
二.動態組件
動態組件就是幾個組件放在一個掛載點下,然後根據父組件的某個變量來決定顯示哪個
在掛載點使用 component 標籤,然後使用 is =“組件名”,它會自動去找匹配的組件名,根據對應的顯示;
1.動態組件實現
html:
<section class="main">
<component :is="current"></component>
</section>
<nav class='nav'>
<a @click="current='index'" href="javascript:">首頁</a>
<a @click="current='find'" href="javascript:">發現</a>
<a @click="current='my'" href="javascript:">我的</a>
</nav>
js:
Vue.component('index', {
template: `
<div>我是首頁內容</div>
`,
beforeCreate() {
console.log('beforeCreate index');
},
beforeDestroy() {
console.log("beforeDestroy index");
}
});
Vue.component('find', {
template: `
<div>我是發現內容</div>
`,
beforeCreate() {
console.log('beforeCreate find');
},
beforeDestroy() {
console.log("beforeDestroy find");
}
});
Vue.component('my', {
template: `
<div>我是我的內容</div>
`,
beforeCreate() {
console.log('beforeCreate my');
},
beforeDestroy() {
console.log("beforeDestroy my");
}
});
const vm = new Vue({
el: '#app',
data: {
current: 'index'
}
});
上述代碼就實現了一個動態組件加載的代碼,其實理解起來很簡單,需要動態加載 的組件共同維護data中的current數據,然後通過需要切換的按鈕給綁定事件,去修改這個current爲當前哪一個組件即可.
但是我們會發現一些問題,當我們每次切換的時候,組件的生命週期鉤子函數也會相應觸發,也就是說動態組件切換時也會有創建銷燬的性能開銷,vue給我們提供了下面的解決辦法:keep-alive
2.keep-alive 狀態保持
Vue 中提供了一個 keep-alive 內置組件。可以實現組件的緩存。
當在這些動態組件之間切換的時候,你有時會想保持這些組件的狀態,以避免反覆重渲染導致的性能問題.在動態組件上使用keep-alive,來實現組件緩存,
<keep-alive>
<component :is="current"></component>
</keep-alive>
使用keep-alive 將component動態組件包裹起來
Vue.component('index', {
template: `
<div>
我是首頁內容
<p>{{name}}</p>
<button @click="name='zhangsan'">修改名字</button>
</div>
`,
beforeCreate() {
console.log('beforeCreate index');
},
beforeDestroy() {
console.log("beforeDestroy index");
},
//當組件被keep-alive緩存時,會調用這個鉤子函數(激活時)
activated() {
console.log("activated index");
},
//當組件被keep-alive緩存時,會調用這個鉤子函數(失活時)
deactivated() {
console.log("deactivated index");
},
data() {
return {
name: 'liuqiao'
}
}
});
Vue.component('find', {
template: `
<div>我是發現內容</div>
`,
beforeCreate() {
console.log('beforeCreate find');
},
beforeDestroy() {
console.log("beforeDestroy find");
}
});
Vue.component('my', {
template: `
<div>我是我的內容</div>
`,
beforeCreate() {
console.log('beforeCreate my');
},
beforeDestroy() {
console.log("beforeDestroy my");
}
});
const vm = new Vue({
el: '#app',
data: {
current: 'index'
}
});
上述代碼中,我要在index組件中修改name屬性,然後切換到其他組件,再切換回來時,keep-aliver已經幫我保存了之前的操作狀態,這就是keep-alive的作用
2.1 被keep-alive緩存組件特點
-
切換組件時,當前組件不會觸發銷燬的生命週期鉤子。也就是說不會銷燬了。
-
切換回來時,也不會重新創建。(既然都沒有被銷燬,哪裏來的重新創建呢)
-
會多出兩個生命週期的鉤子函數
-
activated 緩存激活 第一次會觸發,組件能被看到時
一般跟created鉤子函數做一樣的事情:請求數據
-
deactivated 緩存失活 不能被看到
一般跟beforeDestory做一樣的事情:清除定時器,移除全局事件監聽
-
-
可以在 vue devtools 上看見組件的緩存情況
2.2 keep-alive的更多屬性設置
2.2.1 include 包含
使用方式
- include=“組件1,組件2”
- :include=[“組件1,組件2”] 數組形式,include前必須要有冒號
- :include=’/^hello/’ 正則匹配,方式以hello開頭的
<keep-alive include="index,find">
<component :is="current"></component>
</keep-alive>
只會緩存這兩個組件,其它的不被緩存
2.2.2 exclude排除
使用方式
-
exclude=“組件1,組件2” 注意 逗號前後不要有空格
-
:exclude=[“組件1,組件2”] 數組形式,exclude前必須要有冒號
-
:exclude=’/^hello/’ 正則匹配,方式以hello開頭的排除
- :exclude="[組件1, 組件2]"
- :exclude="/^hello/"
使用方式與include相反
<keep-alive exclude="index,find">
<component :is="current"></component>
</keep-alive>
除了這兩個組件,其它的都被緩存
2.2.3 max 允許最大緩存的數量,默認無限制
<keep-alive :max="5">
<component :is="current"></component>
</keep-alive>
先進先出原則 ,如果緩存隊列有十幾個,當超過最大緩存的數量後,會把第一次進來的擠掉