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