混入是vue官方文檔提出的 關(guān)于vue復(fù)用性的一種方式,看了文檔似懂,查找了下網(wǎng)上的講解,整理下好好縷一縷這個(gè)東西
前言
當(dāng)我們的項(xiàng)目越來越大,我們會(huì)發(fā)現(xiàn)組件之間可能存在很多相似的功能,你在一遍又一遍的復(fù)制粘貼相同的代碼段(data,method,watch、mounted等),如果我們?cè)诿總€(gè)組件中去重復(fù)定義這些屬性和方法會(huì)使得項(xiàng)目出現(xiàn)代碼冗余并提高了維護(hù)難度,針對(duì)這種情況官方提供了Mixins特性
一、什么是Mixins? mixins是一個(gè)js對(duì)象
混入 (mixin) 提供了一種非常靈活的方式,來分發(fā) Vue 組件中的可復(fù)用功能。一個(gè)混入對(duì)象可以包含任意組件選項(xiàng)。當(dāng)組件使用混入對(duì)象時(shí),所有混入對(duì)象的選項(xiàng)將被“混合”進(jìn)入該組件本身的選項(xiàng)。
mixins(混入),官方的描述是一種分發(fā) Vue 組件中可復(fù)用功能的非常靈活的方式,mixins是一個(gè)js對(duì)象,它可以包含我們組件中script項(xiàng)中的任意功能選項(xiàng),如data、components、methods 、created、computed等等。
我們只要將共用的功能以對(duì)象的方式傳入 mixins選項(xiàng)中,當(dāng)組件引用 mixins對(duì)象時(shí)所有mixins對(duì)象的選項(xiàng)都將被混入該組件本身的選項(xiàng)中來,這樣就可以提高代碼的重用性,使你的代碼保持干凈和易于維護(hù)。

放大看這張圖:右邊就是一個(gè)混入對(duì)象; 左邊引用了混入對(duì)象
二、什么時(shí)候使用Mixins?
當(dāng)我們存在多個(gè)組件中的數(shù)據(jù)或者功能很相近時(shí),我們就可以利用mixins將公共部分提取出來,通過 mixins封裝的函數(shù),組件調(diào)用他們是不會(huì)改變函數(shù)作用域外部的。
作用: 減少data、methods、鉤子的重復(fù)
????????
文章最后會(huì)舉例應(yīng)用場(chǎng)景~
三、如何創(chuàng)建Mixins?
在src目錄下創(chuàng)建一個(gè)mixins文件夾,文件夾下新建一個(gè)myMixins.js文件。前面我們說了mixins是一個(gè)js對(duì)象,所以應(yīng)該以對(duì)象的形式來定義myMixins,在對(duì)象中我們可以和vue組件一樣來定義我們的data、components、methods 、created、computed等屬性,并通過export導(dǎo)出該對(duì)象

四、如何使用Mixins?
前面在myMixins.js中輸出一個(gè)混入對(duì)象,然后在需要調(diào)用的組件中引入myMixins.js文件即可

五、Mixins的特點(diǎn)
特點(diǎn)1:方法和參數(shù)在各組件中不共享,雖然組件調(diào)用了mixins并將其屬性合并到自身組件中來了,但是其屬性只會(huì)被當(dāng)前組件所識(shí)別并不會(huì)被共享。
??也就是當(dāng)前組件對(duì)mixins的屬性的修改,其他也引用了這個(gè)mixins的組件并不會(huì)受影響。??
① 首先我們?cè)诨旌蠈?duì)象myMixins.js中定義一個(gè)age字段和getAge方法
export const myMixins = {
components:{},
data() {
return {
age: 18,
}
},
mounted() {
this.getAge()
},
methods: {
getAge() {
console.log(this.age)
}
}
}
② 此時(shí)組件1引用了這個(gè)mixins,組件1中對(duì)num進(jìn)行+1操作
// 這是組件1
import { myMixins } from "@/mixins/myMixins.js";
export default {
mixins: [myMixins],
data() {
return {}
},
created() {
this.age++ // 組件1的age變成了19啦
},
}
③ 組件2不進(jìn)行操作
export default {
mixins: [myMixins],
data() {
return {}
},
}
④ 我們分別切換到兩個(gè)頁面,查看控制臺(tái)輸出。會(huì)發(fā)現(xiàn)組件1改變了age里面的值,組件2中age值還是混合對(duì)象的初始值,并沒有隨著組件1的增加而改變

特點(diǎn)2:引入mixins后,組件會(huì)對(duì)其進(jìn)行合并,將mixins中的數(shù)據(jù)和方法拓展到當(dāng)前組件中來,如果當(dāng)前組件也有同名稱的屬性或者方法,在合并的過程中會(huì)出現(xiàn)沖突,接下來我們?cè)敿?xì)了解Mixins合并沖突
六、Mixins合并沖突
【6.1】混入對(duì)象里的(components、methods 、computed、data)這些選項(xiàng),混入組件時(shí)選項(xiàng)會(huì)被合并,重名沖突時(shí)優(yōu)先采用組件的 ??,組件中的鍵會(huì)覆蓋混入對(duì)象的
① 我們?cè)诨烊雽?duì)象增加age屬性、getAge1方法和getAge2方法
// myMixins.js
export const myMixins = {
components:{},
data() {
return {
age: 18,
}
},
methods: {
getAge1() {
console.log("age1 from mixins =", this.age )
},
getAge2() {
console.log("age2 from mixins =", this.age )
},
}
}
② 我們?cè)谝肓薽yMixins文件的組件中,增加age屬性、getAge1方法和getAge3方法
// template.vue
import { myMixins } from "@/mixins/myMixins.js";
export default {
mixins: [myMixins],
data() {
return {
age: 20,
}
},
mounted() {
this.getAge1();
this.getAge2();
this.getAge3();
},
methods: {
getAge1() {
console.log('age1 from template =', this.age)
},
getAge3() {
console.log('age3 from template =', this.age)
},
}
}
③ 我們會(huì)發(fā)現(xiàn):
組件中的age覆蓋了混合對(duì)象的age,
組件的getAge1方法覆蓋了混合對(duì)象的getAge1方法

【6.2】值為函數(shù)(created、mounted)的選項(xiàng),混入組件時(shí)選項(xiàng)會(huì)被合并調(diào)用,
?? 混合對(duì)象里的鉤子函數(shù)在組件里的鉤子函數(shù)之前調(diào)用
// myMixins.js
export const myMixins = {
components:{},
data() {
return {}
},
created() {
console.log('xxx from mixins')
}
}
再看看引用了mixins的組件
import { myMixins } from "@/mixins/myMixins.js";
export default {
mixins: [myMixins],
data() {
return {}
},
created() {
console.log('xxx from template')
}
}
結(jié)果 mixins自己的created 比 引用了mixins的組件里的created先執(zhí)行

七、全局混入
嚴(yán)重警告:一旦使用全局混入,它將影響每一個(gè)之后創(chuàng)建的 Vue 實(shí)例。
使用恰當(dāng)時(shí),這可以用來為自定義選項(xiàng)注入處理邏輯。
// 為自定義的選項(xiàng) 'myOption' 注入一個(gè)處理器。
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
new Vue({
myOption: 'hello!'
})
// => "hello!"
不建議使用全局混入,全局注冊(cè)之后會(huì)對(duì)所有組件都生效,影響比較大,項(xiàng)目大的情況下,建議使用局部注冊(cè)
八、同時(shí)引入多個(gè)mixin對(duì)象
同時(shí)引入多個(gè) mixins: [mixinsTest2,mixinsTest]
在使用局部注冊(cè)的時(shí)候,可同時(shí)引入多個(gè)混入對(duì)象,執(zhí)行順序和引入順序一致,此處便不再贅述了。
結(jié)論: 引入多個(gè)以后,,我們先引入的先被使用,先引用,先使用!
九、與vuex的區(qū)別
vuex:用來做狀態(tài)管理的,里面定義的變量在每個(gè)組件中均可以使用和修改,在任一組件中修改此變量的值之后,其他組件中此變量的值也會(huì)隨之修改。
Mixins:可以定義共用的變量,在每個(gè)組件中使用,引入組件中之后,各個(gè)變量是相互獨(dú)立的,值的修改在組件中不會(huì)相互影響。
十、與公共組件的區(qū)別
組件:在父組件中引入組件,相當(dāng)于在父組件中給出一片獨(dú)立的空間供子組件使用,然后根據(jù)props來傳值,但本質(zhì)上兩者是相對(duì)獨(dú)立的。
Mixins:則是在引入Mixins之后,Mixins與組件中的屬性和方法進(jìn)行合并,相當(dāng)于擴(kuò)展了父組件的對(duì)象與方法,可以理解為形成了一個(gè)新的組件。
????
另外,vue不建議,子組件直接修改props接收到的父組件的數(shù)據(jù),但是,混入可以做到組件的屬性或者方法覆蓋混入對(duì)象的
混入的應(yīng)用場(chǎng)景
假設(shè)我們需要在每個(gè)組件上添加name和time。在created、destroyed時(shí),打出提示,并給出存活時(shí)間。
一共有五個(gè)組件,請(qǐng)問怎么做?
做法1:給每個(gè)組件添加data和created, destroyed鉤子,重復(fù)5次
做法2:使用mixin減少重復(fù)。
做法1:
<template>
<div>child1</div>
</template>
<script>
export default{
data(){
return {
name:'child1',
time_birth:undefined,
time_dead:undefined
}
},
created(){
this.time_birth=new Date();
console.log(this.name+'出生了');
},
beforeDestroy(){
this.time_dead=new Date();
console.log(`${this.name}死了,共存活了${this.time_dead-this.time_birth}ms`);
}
}
</script>
// 依次對(duì)組件2 3 4 5 分別執(zhí)行這些操作。。。
做法1小結(jié): 代碼重復(fù)太多,基本上每個(gè)組件都在復(fù)刻第一個(gè)組件的樣式,這樣下來,代碼的維護(hù)性是十分低的。萬一有一天要改需求了怎么辦?又倒回去重新修改5次嗎?5次并不是真正的5次,萬一是10次,100次呢?很顯然,這種做法并不可取。接下來來看另外一種做法。
做法2:
創(chuàng)建混入對(duì)象:
const myMixin = {
data(){
return {
/* 每個(gè)組件的名字不同,用另外的方法賦值。即每個(gè)組件自己帶上自己的名字即可。 */
name:undefined,
time_birth:undefined,
time_dead:undefined
}
},
created(){
if(!this.name){
throw new Error('need name'); // 名字是用的組件里data的name
}
this.time_birth=new Date();
console.log(this.name+'出生了');
},
beforeDestroy(){
this.time_dead=new Date();
console.log(`${this.name}死了,共存活了${this.time_dead-this.time_birth}ms`);
}
}
export default myMixin;
組件里
<template>
<div>child1</div>
</template>
<script>
/* 首先導(dǎo)入公共部分的js內(nèi)容 */
import myMixin from './Mixins/public.js';
export default{
data(){
return {
/* 其他組件就寫自己組件的名字即可 */
name:'child1',
}
},
/* 使用導(dǎo)入的public模塊 */
mixins:[myMixin],
}
</script>
用了混入后,組件只需要引用混入對(duì)象,然后在data里填寫組件的名字,再掛載一下混入對(duì)象,就好了。
今天就聊到這里,后續(xù)有想到栗子再補(bǔ)充吧 ??
??