DAY18 | 跟 Vue.js 認識的30天 - Vue 混入(`mixin`)

混入(mixin)似乎也是個初學 Vue 比較少被用到的功能,但還是照順序的了解一下。

基礎運用

在模組中如果有重複出現的模組 option 內容,就可以透過 mixin 將其獨立,並匯入到會使用到該內容的模組裡。

透過創建一個新變數A將重複出現的模組 option 內容集結起來後,再用 mixins:[變數名A] 將資料匯入到模組中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<component-a></component-a>
<p>根模組 mixinData :{{mixinData}}</p><!--根模組 mixinData :我是被匯入(mixin)的資料-->
<p>根模組 mixinNum :{{mixinNum}}</p><!--根模組 mixinNum :10-->
<p>根模組 computedNum :{{computedNum}}</p><!--根模組 computedNum :11-->

<script>
const Mymixin = {
created() {
this.mixinData = "我是被匯入(mixin)的資料";
},
computed: {
computedNum() {
return this.mixinNum+1;
}
}
};
Vue.component("component-a", {
mixins: [Mymixin],
template: `<div>
<p>模組內 mixinData :{{mixinData}}</p><!--模組內 mixinData :我是被匯入(mixin)的資料-->
<p>模組內 mixinNum :{{mixinNum}}</p><!--模組內 mixinNum :0-->
<p>模組內 computedNum :{{computedNum}}</p><!--模組內 mixinNum :0-->
</div>`,
data() {
return {
mixinData: "",
mixinNum: 0
};
}
});

const vm = new Vue({
el: "#vm",
mixins: [Mymixin],
data: {
mixinData: "",
mixinNum: 10
}
});
</script>

發生衝突時的選項合併

以下是在匯入的資料跟模組發生衝突時,Vue 本身對衝突的解決方法。
假設匯入資料跟模組資料具有相同的數據資料

數據資料

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<component-a></component-a>
<p>根模組 mixinNum :{{mixinNum}}</p>
<p>根模組 computedNum :{{computedNum}}</p>
<button @click="conflicting">試試重複的methods,打開console</button>
<script>
const Mymixin = {
data() {
return {
mixinData: "我是mixin內的資料",
mixinNum: 50
};
},
computed: {
computedNum() {
console.log("我是被匯入(mixin)的computedNum資料");
return this.mixinNum + 1;
}
},
methods: {
conflicting() {
console.log("from mixin");
}
}
};
Vue.component("component-a", {
mixins: [Mymixin],
template: `<div>
<p>模組內 mixinNum :{{mixinNum}}</p>
<p>模組內 computedNum :{{computedNum}}</p>
<button @click="conflicting">試試重複的methods,打開console</button>
</div>`,
data() {
return {
mixinNum: 0
};
},
computed: {
computedNum() {
console.log("我是模組內原本的computedNum資料");
return this.mixinNum + 20;
}
},
methods: {
conflicting() {
console.log("模組內");
}
}
});

const vm = new Vue({
el: "#vm",
mixins: [Mymixin],
data: {
mixinNum: 10
},
computed: {
computedNum() {
console.log("我是根模組內原本computedNum資料");
return this.mixinNum + 100;
}
},
methods: {
conflicting() {
console.log("根模組");
}
}
});
</script>

在上面的例子中會發現: mixins 及模組內的數據資料如果發生衝突,最後一定是模組內的資料獲勝(得到的一定是模組內的資料),我自己理解為模組內的數據資料會直接取代掉 mixins 內的數據資料,以 conflicting() 得知在 console 中 mixinsconflicting() 連出現都沒有出現。

鉤子函數(lifecycle hooks)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<component-a></component-a>
<p>根模組 mixinNum :{{mixinNum}}</p>
<p>根模組 computedNum :{{computedNum}}</p>
<button @click="conflicting">試試重複的methods,打開console</button>
<script>
const Mymixin = {
created() {
console.log("我是被匯入(mixin)的資料");
this.mixinData = "我是被匯入(mixin)的資料";
}
};
Vue.component("component-a", {
mixins: [Mymixin],
template: `<div>
</div>`,
data() {
return {
mixinData: ""
};
},
created() {
console.log("我是模組內原本的資料");
this.mixinData = "我是模組內原本的資料";
}
});

const vm = new Vue({
el: "#vm",
mixins: [Mymixin],
data: {
mixinData: ""
},
created() {
console.log("我是根模組內原本資料");
this.mixinData = "我是根模組內原本的資料";
}
});
</script>

最後 console 出現的順序如下圖

在上面的例子中會發現: mixins 及模組內的鉤子函數都會被執行,但是模組的鉤子函數一定比 mixins 的晚出現,這代表模組的鉤子函數會去覆蓋 mixins 的,如果在鉤子函數中有資料被變更了,那麼就是 mixins 的鉤子函數會先將資料修改 → 模組的鉤子函數在修改一次資料,最終顯示的資料內容還是模組變更的那些。

Vue 在處理 mixins 跟模組數據資料及鉤子函數衝突時的不同:

發生衝突 數據資料 鉤子函數
mixins 不執行 執行
模組 執行 執行
處理方式 模組取代mixins 模組覆蓋mixins

全域註冊 mixin –不建議使用

因為會影響所有模組因為會影響所有模組(包含第三方插件),所以不建議使用全域註冊 mixin

1
2
3
Vue.mixin({
// options
})

不須在模組內使用 mixins:[...] 載入了。

Demo

See the Pen DAY18 | 跟 Vue.js 認識的30天 - Vue 模組混入(`mixin`) by Celeste6666 (@celeste6666) on CodePen.

參考資料

Vue.js - 混入