1. 前言
本節(jié)介紹混入 (mixin) 的使用方法。包括什么是 mixin,如何定義 mixin,mixin 重名屬性的合并策略,全局 mixin 的使用。其中,了解和掌握 mixin 重名屬性的合并策略非常重要,屬性合并問題會在 mixin 的使用中經(jīng)常出現(xiàn)。在學(xué)完本小節(jié)之后,同學(xué)們可以嘗試總結(jié)出屬性的合并的規(guī)則策略,這有助于加深印象,在日后的使用中也能得心應(yīng)手。
2. 慕課解釋
混入 (mixin) 提供了一種非常靈活的方式,來分發(fā) Vue 組件中的可復(fù)用功能。一個混入對象可以包含任意組件選項(xiàng)。當(dāng)組件使用混入對象時,所有混入對象的選項(xiàng)將被 “混合” 進(jìn)入該組件本身的選項(xiàng)。 – 官方定義
我們在日常開發(fā)中經(jīng)常遇到多個頁面或者功能模塊有相同代碼邏輯的情況,同學(xué)們在遇到此類情況的時候肯定會想:如果這段代碼能夠復(fù)用就好了!。那什么方法可以幫助我們實(shí)現(xiàn)復(fù)用呢?答案就是:Mixin! Mixin
幫助我們抽離公共代碼邏輯。一個混入對象可以包含任意組件選項(xiàng)。當(dāng)組件使用混入對象時,所有混入對象的選項(xiàng)將被 “混合” 進(jìn)入該組件本身的選項(xiàng)。
3. 使用 mixin
接下來我一起看看如何定義和使用一個 mixin。
對于 mixin 的使用可以分為兩部分:
- 定義 mixin
- 混入 mixin
3.1 定義一個 mixin
mixin 本質(zhì)上就是一個 Object 對象,它和 vue
實(shí)例上的屬性一致,包含 data、methods、computed、watch、生命周期函數(shù)等等:
var myMixin = {
data(){
return {
//...
}
},
created() {
//...
},
methods: {
//...
},
computed() {
// ...
}
}
3.2 混入 mixin
想要混入定義好的 mixin,只需要通過組件的 mixins 屬性傳入想要混入的 mixin 數(shù)組即可:
var vm = new Vue({
el: '#app',
mixins:[myMixin]
})
代碼解釋:
上述代碼中,我們定義了一個 Vue 實(shí)例,并在實(shí)例上混入 myMixin。
接下來我們看一個簡單的示例:
<!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">
我是:{{name}}, 年齡:{{year}}
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
// 定義 mixin
var myMixin = {
data(){
return {
name: '句號'
}
},
created: function () {
this.mixinFun()
},
methods: {
mixinFun: function () {
console.log('mixin function')
}
}
};
var vm = new Vue({
el: '#app',
// 使用mixin
mixins:[myMixin],
data() {
return {
year: '18'
}
}
})
</script>
</html>
代碼解釋:
JS 代碼第 3-17 行,定義了一個混入對象 myMixin,并定義了數(shù)據(jù) data、鉤子函數(shù) created、方法 mixinFun。
JS 代碼第 20 行,通過組件實(shí)例上的 mixins 屬性引入 myMixin。
運(yùn)行程序可以看到,在 myMixin 中定義的數(shù)據(jù) name 渲染到頁面上。同時打開控制臺可以看到 ‘mixin function’ 被打印出來,說明 created 鉤子函數(shù)被執(zhí)行。
4. 選項(xiàng)合并
我們在定義 mixin
時會出現(xiàn)屬性名重復(fù)的情況,例如:
var myMixin = {
data() {
return {
name: 'Imooc'
}
},
create() {
console.log('Imooc')
}
}
var vm = new Vue({
data() {
return {
name: '句號'
}
},
create() {
console.log('句號')
}
})
當(dāng)組件和混入對象含有同名選項(xiàng)時,這些選項(xiàng)將以恰當(dāng)?shù)姆绞竭M(jìn)行 “合并”。這些重復(fù)項(xiàng)的合并有固定的規(guī)則,接下來我們從三個方面來詳細(xì)講解選項(xiàng)合并的規(guī)則。
4.1 data 的合并
數(shù)據(jù)對象在內(nèi)部會進(jìn)行遞歸合并,并在發(fā)生沖突時以組件數(shù)據(jù)優(yōu)先。詳細(xì)的合并規(guī)則如下:
- 首先判斷 mixin 中的數(shù)據(jù)類型和組件實(shí)例對象上的數(shù)據(jù)類型是否相同;
- 如果不同,組件實(shí)例上的數(shù)據(jù)將覆蓋 mixin 上的數(shù)據(jù);
- 如果相同,判斷是否為 Object 的數(shù)據(jù)格式;
- 如果不是 Object 的數(shù)據(jù)格式,組件實(shí)例上的數(shù)據(jù)將覆蓋 mixin 上的數(shù)據(jù);
- 如果是 Object 的數(shù)據(jù)格式,從第一步開始循環(huán)判斷 Object 的每一個屬性。
具體示例:
<!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"></div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
var myMixin = {
data(){
return {
isOpen: false,
date: '2020-02-02',
desc: {
title: 'Mixins 基礎(chǔ)教程',
desc: '本教程將講解如何使用 mixins',
author: {
name: '慕課網(wǎng)',
location: '北京'
}
}
}
}
};
var vm = new Vue({
el: '#app',
mixins:[myMixin],
data() {
return {
isOpen: true,
date: new Date().toLocaleString(),
desc: {
author: {
name: 'Imooc',
age: '20'
}
}
}
},
created() {
console.log(this.data)
}
})
</script>
</html>
代碼解釋:
JS 代碼第 3-15 行,定義了一個混入對象 myMixin,并定義了數(shù)據(jù) data。
JS 代碼第 18 行,通過組件實(shí)例上的 mixins 屬性引入 myMixin。
JS 代碼第 19-30 行,定義了組件實(shí)例上的數(shù)據(jù) data。
根據(jù)之前我們學(xué)習(xí)的合并規(guī)則,得到的最終數(shù)據(jù) data 格式如下:
data() {
return {
isOpen: true,
date: new Date().toLocaleString(),
desc: {
author: {
name: 'Imooc',
age: '20',
location: '北京'
}
}
}
}
4.2 鉤子 的合并
同名鉤子函數(shù)將合并為一個數(shù)組,因此都將被調(diào)用。另外,混入對象的鉤子將在組件自身鉤子之前調(diào)用。也就是說,如果我們在 mixin 和組件中都定義了鉤子函數(shù) created,那么 mixin 和 組件中的函數(shù)都會被執(zhí)行。需要注意的是:mixin 中的鉤子函數(shù)將在組件的鉤子函數(shù)之前執(zhí)行。
具體示例:
<!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">
mixin 示例
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
var myMixin = {
created() {
alert('mixin created 先執(zhí)行')
}
};
var vm = new Vue({
el: '#app',
mixins:[myMixin],
created() {
alert('組件 created 后執(zhí)行')
}
})
</script>
</html>
代碼解釋:
JS 代碼第 3-7 行,定義了一個混入對象 myMixin,并定義了鉤子函數(shù) created。
JS 代碼第 10 行,混入定義的 myMixin。
JS 代碼第 11-13 行,在組件內(nèi)部定義了鉤子函數(shù) created。
所以,最終的運(yùn)行結(jié)果是:
mixin created 執(zhí)行
組件 created 執(zhí)行
4.3 值為對象的選項(xiàng)合并
值為對象的選項(xiàng),例如 methods、components 和 directives,將被合并為同一個對象。兩個對象鍵名沖突時,取組件對象的鍵值對。
示例:
<!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">
mixin 示例
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
var myMixin = {
methods: {
sayName() {
console.log('我是慕課網(wǎng)')
},
sayHello() {
console.log('hello 大家好')
}
}
};
var vm = new Vue({
el: '#app',
mixins:[myMixin],
methods: {
sayName() {
console.log('我是句號')
},
sayYear() {
console.log('我的年齡是:18')
}
}
})
vm.sayName() // ---> 我是句號
vm.sayHello() // ---> hello 大家好
vm.sayYear() // ---> 我的年齡是:18
</script>
</html>
代碼解釋:
JS 代碼第 3-12 行,定義了一個混入對象 myMixin,并定義了兩個方法。
JS 代碼第 15 行,混入定義的 myMixin。
JS 代碼第 16-23 行,在組件內(nèi)部定義了兩個方法。
由于值為對象的選項(xiàng)合并取組件對象的鍵值對。所以,最終的 methods 對象是:
methods: {
sayName() {
console.log('我是句號')
},
sayYear() {
console.log('我的年齡是:18')
},
sayHello() {
console.log('hello 大家好')
}
}
5. 全局混入
混入也可以進(jìn)行全局注冊。使用時需要格外小心!一旦使用全局混入,它將影響每一個之后創(chuàng)建的 Vue 實(shí)例。使用恰當(dāng)時,這可以用來為自定義選項(xiàng)注入處理邏輯。通過 Vue.mixin ({…}) 可以注冊全局混入:
Vue.mixin({
data: {
name: "Imooc"
}
})
具體示例:
<!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">
mixin 全局混入 示例
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.mixin({
created() {
console.log('全局mixin created')
},
methods: {
sayHello() {
console.log('hello 大家好')
}
}
})
var vm = new Vue({
el: '#app'
})
vm.sayHello()
</script>
</html>
代碼解釋:
JS 代碼第 3-12 行,定義了一個全局混入對象,并定義了鉤子函數(shù) created 和 sayHello 方法。
JS 代碼第 14-16 行,創(chuàng)建了 Vue 實(shí)例。
因?yàn)槿只烊霑谥髣?chuàng)建的每一個 Vue 實(shí)例上混入,所以,控制臺會輸出以下數(shù)據(jù):
全局 mixin created
hello 大家好
6. 小結(jié)
本節(jié),我們帶大家學(xué)習(xí)了混入 mixin 在 vue 項(xiàng)目中的運(yùn)用。主要知識點(diǎn)有以下幾點(diǎn):
- Mixin 的定義和使用方法。
- Mixin 選項(xiàng)的合并策略。
- 全局 Mixin 的注冊和使用。