動(dòng)態(tài)組件的使用(了解)
切換組件案例:
比如我們現(xiàn)在想要實(shí)現(xiàn)了一個(gè)功能:
- 點(diǎn)擊一個(gè)tab-bar,切換不同的組件顯示;
這個(gè)案例我們可以通過兩種不同的實(shí)現(xiàn)思路來實(shí)現(xiàn):
-
方式一
:通過v-if來判斷,顯示不同的組件; -
方式二
:動(dòng)態(tài)組件的方式;
方式一代碼示例:
<template>
<div class="app">
<div class="tabs">
<template v-for="(item, index) in tabs" :key="item">
<button @click="changeColor(index)" :class="{ active: index === currentIndex }">
{{ item }}
</button>
</template>
</div>
<div class="view">
<!-- 1.第一種做法:v-if進(jìn)行邏輯判斷,決定要顯示哪一個(gè)組件 -->
<template v-if="currentIndex === 0">
<home></home>
</template>
<template v-else-if="currentIndex ===1">
<about></about>
</template>
<template v-else-if="currentIndex === 2">
<category></category>
</template>
<!-- 最后一個(gè)寫<template v-else> 也可以,但是不推薦-->
</div>
</div>
</template>
<script>
import About from "./views/About.vue";
import Category from "./views/Category.vue";
import Home from "./views/Home.vue";
export default {
components: {
Home,
Category,
About
},
data() {
return {
tabs: ["home", "about", "category"],
currentIndex: 0
}
},
methods: {
changeColor(index) {
this.currentIndex = index
}
}
}
</script>
動(dòng)態(tài)組件方式實(shí)現(xiàn)
動(dòng)態(tài)組件是使用component組件
,通過一個(gè)特殊的attribute is
來實(shí)現(xiàn):
<template>
<div class="app">
<div class="tabs">
<template v-for="(tab, index) in tabs" :key="item">
<button @click="changeColor(tab)" :class="{ active: currentTab === tab }">
{{ tab }}
</button>
</template>
</div>
<div class="view">
<!-- 2.第二種做法:動(dòng)態(tài)組件:component -->
<!-- is中的組件:(1)要么是全局注冊(cè)的組件;(2)要么是局部注冊(cè)過的組件 -->
<!-- <component is="about"></component> -->
<!-- 動(dòng)態(tài)組件傳參(了解),如果是數(shù)組類型就和age一樣: 監(jiān)聽發(fā)送的事件也在component上 -->
<!-- <component name="sevgilid" :age="19" :is="tabs[currentIndex]"></component> -->
<component name="sevgilid" :age="19" :is="currentTab"></component>
</div>
</div>
</template>
在上面的演示中,我們可以看到:
- 首先
使用了component組件,is:組件名
,來展示對(duì)應(yīng)的組件; - 然后綁定事件
點(diǎn)擊按鈕時(shí)獲取對(duì)應(yīng)的tab來作為組件名實(shí)現(xiàn)動(dòng)態(tài)組件
的展示 - 傳遞參數(shù)和監(jiān)聽子組件事件正常在component組件內(nèi)使用即可,如在home組件中使用props接收數(shù)據(jù):
(動(dòng)態(tài)組件了解即可,后邊會(huì)講解路由,使用路由切換更為簡潔遍歷)
keep-alive(理解)
認(rèn)識(shí)keep-alive
在 Vue.js 中, keep-alive 內(nèi)置組件可以緩存不活動(dòng)的組件實(shí)例,它通過包裹動(dòng)態(tài)組件來實(shí)現(xiàn)緩存
,避免了組件的頻繁銷毀和重建,從而提升了頁面性能
。
我們先對(duì)之前的案例中Home組件進(jìn)行改造:
- 在其中增加了一個(gè)按鈕,點(diǎn)擊可以遞增的功能;
比如我們將counter點(diǎn)到10,那么在切換到about再切換回來Home時(shí),狀態(tài)是否可以保持呢?
- 答案是否定的;
- 這是因?yàn)槟J(rèn)情況下,我們?cè)?code>切換組件后,Home組件會(huì)被銷毀掉,再次回來時(shí)
會(huì)重新創(chuàng)建組件
;
但是,在開發(fā)中某些情況我們希望繼續(xù)保持組件的狀態(tài),而不是銷毀掉,這個(gè)時(shí)候我們就可以使用一個(gè)內(nèi)置組件: keep-alive
keep-alive的使用
使用 keep-alive 內(nèi)置組件很簡單,只需要將需要緩存的組件用 <KeepAlive> 標(biāo)簽包裹
即可。例如在剛才的案例中:
像上面這樣包裹后,我們?cè)邳c(diǎn)擊遞增按鈕到一定數(shù)值后來回切換發(fā)現(xiàn)已經(jīng)數(shù)值不會(huì)再被重置;
但通過再各個(gè)組件內(nèi)部使用created和unmounted鉤子函數(shù)發(fā)現(xiàn)都沒有回調(diào)
,這說明里面被包裹的所有組件都被緩存了
;
如果想要精準(zhǔn)控制組件的緩存
和對(duì)保持keep-alive組件監(jiān)聽有沒有切換
該怎么辦呢?
(1)精準(zhǔn)控制組件緩存
keep-alive有一些屬性:
-
include
- string | RegExp |Array。只有名稱匹配的組件會(huì)被緩存; -
exclude
- string | RegExp | Array。任何名稱匹配的組件都不會(huì)被緩存; -
max
- number | string。最多可以緩存多少組件實(shí)例,一旦達(dá)到這個(gè)數(shù)字,那么緩存組件中最近沒有被訪問的實(shí)例會(huì)被銷毀;
include和exclude prop允許組件有條件地緩存:
- 二者都可以
用逗號(hào)分隔字符串、正則表達(dá)式或一個(gè)數(shù)組
來表示; - 匹配首先檢查組件自身的
name選項(xiàng)
;
使用示例:
Home組件中:
<template>
<h2>home組件</h2>
<h2>計(jì)數(shù)器:{{ counter }}</h2>
<button @click="counter++">+1</button>
</template>
<script>
export default {
// 此處的name提供給Keep-Alive中的include屬性使用的
name: "home",
data() {
return {
counter: 0
}
}
}
</script>
App根組件中:
(2)緩存組件的生命周期
對(duì)于緩存的組件來說,再次進(jìn)入時(shí),我們是不會(huì)執(zhí)行created或者mounted
等生命周期函數(shù)的:
- 但是有時(shí)候我們確實(shí)希望監(jiān)聽到何時(shí)重新進(jìn)入到了組件,何時(shí)離開了組件;
- 這個(gè)時(shí)候我們可以使用
activated和deactivated
這兩個(gè)生命周期鉤子函數(shù)來監(jiān)聽;
需要注意的是,由于 keep-alive 是內(nèi)置組件,所以不支持動(dòng)態(tài)組件模式下的異步組件
:
- 因?yàn)楫惒浇M件的加載是異步的, keep-alive 無法知道異步組件何時(shí)完成加載,從而無法對(duì)其進(jìn)行緩存;
- 如果
需要緩存異步組件
,可以使用工廠函數(shù)與異步組件創(chuàng)建一個(gè)高階組件
,再將其包裹在 keep-alive 內(nèi);
異步組件的使用
在學(xué)習(xí)異步組件使用前,先來了解一下webpack的分包處理,因?yàn)楫惒浇M件打包時(shí)會(huì)進(jìn)行分包的處理
webpack分包處理(了解)
默認(rèn)的打包過程:
- 默認(rèn)情況下,在構(gòu)建整個(gè)組件樹的過程中,因?yàn)榻M件和組件之間是
通過模塊化直接依賴的
,那么webpack在打包時(shí)就會(huì)將組件模塊打包到一起
(比如一個(gè)app.js文件中); - 這個(gè)時(shí)候隨著
項(xiàng)目的不斷龐大,app.js文件的內(nèi)容過大
,會(huì)造成首屏的渲染速度變慢
;
打包時(shí),代碼的分包:
- 所以,對(duì)于一些
不需要立即使用的組件
,我們可以單獨(dú)對(duì)它們進(jìn)行拆分
,拆分成一些小的代碼塊chunk.js
; - 這些chunk.js會(huì)在需要時(shí)
從服務(wù)器加載下來
,并且運(yùn)行代碼
,顯示對(duì)應(yīng)的內(nèi)容;
那么webpack中如何可以對(duì)代碼進(jìn)行分包呢?
Vue中實(shí)現(xiàn)異步組件
如果我們的項(xiàng)目過大了,對(duì)于某些組件
我們希望通過異步的方式來進(jìn)行加載
(目的是可以對(duì)其進(jìn)行分包處理),那么Vue中給我們提供了一個(gè)函數(shù): defineAsyncComponent
defineAsyncComponent接受兩種類型的參數(shù):
-
類型一
:工廠函數(shù),該工廠函數(shù)需要返回一個(gè)Promise對(duì)象; -
類型二
:接受一個(gè)對(duì)象類型,對(duì)異步函數(shù)進(jìn)行配置;
工廠函數(shù)類型一的寫法:
<script>
import { defineAsyncComponent } from "vue";
// import Category from "./views/Category.vue";
// 異步組件寫法一(了解):工廠函數(shù):返回的是一個(gè)promise對(duì)象
const AsyncCategory = defineAsyncComponent(() => import("./views/Category.vue"))
export default {
components: {
Home,
// 異步組件:打包的時(shí)候會(huì)進(jìn)行分包處理
Category: AsyncCategory,
}
}
</script>
異步組件寫法二(了解):
(異步組件的使用僅作了解即可,因?yàn)閷?shí)際開發(fā)中路由懶加載的寫法會(huì)更多)
組件的v-model
前面我們?cè)?code>input中可以使用v-model
來完成雙向綁定:
- 這個(gè)時(shí)候往往會(huì)非常方便,因?yàn)関-model默認(rèn)幫助我們完成了兩件事;
-
v-bind:value的數(shù)據(jù)綁定
和@input的事件監(jiān)聽
;
如果我們現(xiàn)在封裝了一個(gè)組件,其他地方在使用這個(gè)組件時(shí),是否也可以使用v-model來同時(shí)完成這兩個(gè)功能呢?
- 也是可以的,vue也支持
在組件上使用v-model
;
當(dāng)我們?cè)诮M件上使用的時(shí)候,等價(jià)于如下的操作:
- 我們會(huì)發(fā)現(xiàn)
和input元素不同的只是屬性的名稱和事件觸發(fā)的名稱
而已;
那么,為了我們的counter組件可以正常的工作,這個(gè)組件內(nèi)的click必須:
- 將其value attribute綁定到一個(gè)名叫
modelValue 的prop
上; - 在其click事件被觸發(fā)時(shí),將新的值通過
自定義的update:modelValue事件
拋出;
Counter組件代碼如下:
<template>
<h2>counter:{{ modelValue }}</h2>
<button @click="changeCounter">修改counter</button>
</template>
<script>
export default{
props:{
modelValue:{
type:Number,
default:0
}
},
emits:["update:modelValue"],
methods:{
changeCounter(){
// this.$emit("update:modelValue", 1000)
this.$emit("update:modelValue", 999)
}
}
}
</script>
v-model默認(rèn)綁定的參數(shù)名和事件名是modelValue;
此處的@click綁定click事件;換成@input則表示的是綁定的是input事件,當(dāng)input表有input輸入時(shí)觸發(fā)事件
綁定多個(gè)屬性(高級(jí)用法):
我們現(xiàn)在通過v-model是直接綁定了一個(gè)屬性,如果我們希望綁定多個(gè)屬性呢?
- 也就是我們希望在
一個(gè)組件上使用多個(gè)v-model
是否可以實(shí)現(xiàn)呢? - 我們知道,
默認(rèn)情況
下的v-model其實(shí)是綁定了modelValue屬性
和@update:modelValue
的事件; - 如果我們希望綁定更多,可以
給v-model傳入一個(gè)參數(shù)
,那么這個(gè)參數(shù)的名稱就是我們綁定屬性的名稱
;
默認(rèn)綁定一個(gè)屬性和綁定多個(gè)自定義屬性的代碼對(duì)比:
(1)子組件部分:
(2)父組件部分:
總結(jié):
- v-model可以綁定多個(gè)自定義屬性
- v-model在組件上的應(yīng)用實(shí)際上是將一個(gè)代表數(shù)據(jù)的屬性和一個(gè)代表數(shù)據(jù)修改的事件綁定到了一起,使得在父子組件之間進(jìn)行數(shù)據(jù)通信變得簡單和直觀。 比如v-model:title相當(dāng)于做了兩件事:
綁定了title屬性;
監(jiān)聽了@update:title的事件;
組件的混入Mixin(了解)
Mixin主要在Vue2中使用,在Vue3中基本不用
雖然mixin在Vue中給我們帶來了很多的代碼復(fù)用和邏輯復(fù)用的好處,但是也存在一些弊端:
- 命名沖突:mixin可以將通用的邏輯和代碼分離出來,但是它也可能導(dǎo)致命名沖突。如果多個(gè)Mixin中有同名的選項(xiàng),或者M(jìn)ixin中的選項(xiàng)與組件中的選項(xiàng)重名,就會(huì)導(dǎo)致選項(xiàng)的合并沖突。而且如果有多個(gè)mixin混合使用可能會(huì)更加復(fù)雜,因?yàn)殡y以判斷選項(xiàng)的來源和優(yōu)先級(jí)。為了避免命名沖突,我們需要在編寫Mixin時(shí)格外小心,同時(shí)在開發(fā)過程中也需要保持清晰的組織結(jié)構(gòu)。
- 耦合性高:mixin雖然可以讓我們方便地復(fù)用代碼和邏輯,但是也可能導(dǎo)致組件與Mixin之間的耦合性增加。因?yàn)閙ixin需要了解組件的內(nèi)部實(shí)現(xiàn)細(xì)節(jié)和數(shù)據(jù)結(jié)構(gòu),從而才能正確地暴露需要的數(shù)據(jù)和方法。這就導(dǎo)致了Mixin與組件之間的耦合度會(huì)比較高,一旦需要修改Mixins,可能會(huì)對(duì)組件產(chǎn)生意外的影響。
在Vue 3中,Composition API的出現(xiàn)主要是為了解決mixin中所存在的問題和局限性。Composition API可以更好地實(shí)現(xiàn)邏輯復(fù)用,并且可以更好地組織組件代碼。通過Composition API,我們可以將邏輯功能組織成一組Hooks(鉤子函數(shù))并進(jìn)行復(fù)用。
目前我們是使用組件化的方式在開發(fā)整個(gè)Vue的應(yīng)用程序,但是組件和組件之間有時(shí)候會(huì)存在相同的代碼邏輯,我們希望對(duì)相同的代碼邏輯進(jìn)行抽取。
在Vue2和Vue3中都支持的一種方式就是使用Mixin來完成:
- Mixin提供了一種非常靈活的方式,來
分發(fā)Vue組件中的可復(fù)用功能
; - 一個(gè)Mixin對(duì)象可以包含
任何組件選項(xiàng)
; - 當(dāng)組件使用Mixin對(duì)象時(shí),所有
Mixin對(duì)象的選項(xiàng)將被混合進(jìn)入該組件本身的選項(xiàng)
中;
(1)基本使用:
Vue中的Mixin分為全局Mixin與組件級(jí)Mixin。下面我們以組件級(jí)Mixin為例講解其基本使用方法。
首先,定義一個(gè)名為myMixin的mixin:
var myMixin = {
data: function () {
return {
message: 'Hello world!'
}
},
methods: {
greet: function () {
console.log(this.message)
}
}
}
然后,可以在Vue組件中使用這個(gè)mixin了。我們需要在組件中使用mixins選項(xiàng)來將Mixin混入(mixin)到組件中。
Vue.component('my-component', {
mixins: [myMixin],
template: '<div>{{ message }}</div>',
created: function () {
this.greet() // 執(zhí)行myMixin中的方法greet
}
})
在上面的代碼中,我們將myMixin混入到了my-component組件中。所以在my-component組件中,我們可以使用myMixin中定義的message實(shí)例屬性和greet方法。
(2)mixin的合并規(guī)則
當(dāng)多個(gè)Mixin共同作用于一個(gè)組件的時(shí)候,Vue中的Mixin會(huì)按照一定的規(guī)則進(jìn)行合并;如果多個(gè)Mixin有相同的選項(xiàng)
,這些選項(xiàng)會(huì)被合并到一個(gè)選項(xiàng)
中,合并規(guī)則如下:
- 數(shù)據(jù)對(duì)象:在組件和Mixin中定義的數(shù)據(jù)對(duì)象會(huì)被合并成一個(gè)對(duì)象。當(dāng)組件與Mixin同名的屬性沖突時(shí),以組件數(shù)據(jù)為準(zhǔn)。
- 生命周期鉤子函數(shù):合并兩個(gè)Mixin中的同名生命周期鉤子時(shí),都會(huì)被調(diào)用。Mixin的鉤子總是在組件的鉤子之前被調(diào)用。
- 方法:Mixin中的方法會(huì)被合并到組件中,并且優(yōu)先級(jí)高于組件中的同名方法。
- 其他選項(xiàng):如
props、computed
等,都會(huì)以和方法相同的方式進(jìn)行合并。
(3)全局混入mixin
全局混入Mixin的主要作用是向所有的Vue實(shí)例添加一些全局的邏輯或方法。這樣一來,我們就可以在所有Vue實(shí)例內(nèi)使用這些全局的邏輯或方法。
比如,我們可以在全局Mixin中添加一個(gè)$myMethod
方法:
Vue.mixin({
methods: {
$myMethod: function () {
console.log('This is a global method.')
}
}
})
通過上面的代碼,我們就向所有的Vue實(shí)例中添加了一個(gè)全局方法$myMethod
,可以在任何Vue組件內(nèi)使用。文章來源:http://www.zghlxwxcb.cn/news/detail-478790.html
new Vue({
created: function () {
this.$myMethod() //這里就可以調(diào)用到已經(jīng)全局混合的$myMethod方法了
}
})
總結(jié):文章來源地址http://www.zghlxwxcb.cn/news/detail-478790.html
- 全局的Mixin可以使用應(yīng)用app的方法mixin來完成注冊(cè);
- 一旦注冊(cè),那么全局混入的選項(xiàng)將會(huì)影響每一個(gè)組件;
到了這里,關(guān)于【vue3】10-vue組件化額外知識(shí)補(bǔ)充(下)-動(dòng)態(tài)組件-組件緩存-v-model在組件上的應(yīng)用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!