首先是官方定義:混入 (mixin) 提供了一種非常靈活的方式,來分發 Vue 組件中的可復用功能。一個混入對象可以包含任意組件選項。當組件使用混入對象時,所有混入對象的選項將被“混合”進入該組件本身的選項。
通俗來講,就是 mixin 中的屬性,比如 data、methods 或者自定義屬性,將被混入到全部或者指定的組件中,讓這些組件可以調用 mixin 中所定義的屬性或者事件
全局 mixin
首先,我們直接定義全局的 mixin
// 定義全局 mixin
app.mixin({
message: 'mixin',
data() {
return {
count: 100,
};
},
});
混入 data
全局mixin默認會混入所有組件中,接下來,我們再定義一個組件,模板中插入 message
字段,如下所示:
const app = Vue.createApp({
template: `
<div>{{message}}</div>
`,
});
此時mixin中的data屬性將會混入到組件中,雖然組件的 data 中並沒有包含 message 字段,但是在運行的頁面中依然顯示出 message 的值 mixin message
。現在,我們在組件內部的 data 中也添加 message 字段。
const app = Vue.createApp({
data() {
return {
message:'app message'
}
}
...
});
這時候,運行頁面,模板中的內容將顯示組件中 data 里的值 app message
,這說明,組件內部 data 的優先級是高於 mixin 內部 data 的優先級的。
混入事件(methods)
同樣的,我們也可以一下測試事件的優先級
const app = Vue.createApp({
...
methods: {
handleClick() {
console.log('app click');
}
},
// 這里點擊元素,會打印出 "app click"
template: "<div @click="handleClick">{{message}}</div>"
});
// 定義全局 mixin
app.mixin({
...
methods: {
handleClick() {
console.log('mixin click');
}
}
});
點擊div,將會打印出 app click
,這說明當 mixin 中和組件中都存在 handleClick 事件時,組件中同名事件優先級會比較高。
混入生命周期函數(created、mounted 等)
下面,我們同時在 mixin 和 app 中定義 created
函數
const app = Vue.createApp({
...
created() {
console.log("app created");
}
});
// 定義全局 mixin
app.mixin({
created() {
...
console.log("mixin created");
}
});
運行此頁面,打印台會輸出
mixin created
app created
也就是說,mixin中的生命周期鈎子函數與 app 組件中的鈎子函數都會運行,mixin 優先執行
混入自定義屬性
我們還可以直接在 mixin 和 app 組件中自定義屬性。自定義屬性在模板中需要用 $options[prop]
的方式調用
const app = Vue.createApp({
message: "app message",
template: "<div @click="handleClick">{{$options.message}}</div>"
});
// 定義全局 mixin
app.mixin({
message: "mixin message"
});
運行頁面,模板將會展示 app 組件中 message 中的值 app message
,可見,自定義屬性也是組件比 mixin 優先級高。
修改自定義屬性合並策略
如果我們想讓 mixin 的優先級高於組件的優先級,我們可以通過以下代碼進行修改
app.config.optionMergeStrategies.message = (mixinVal, appVal) => {
return mixinVal || appVal;
};
合並策略方法中接受兩個參數,第一個參數為 mixin 自定義屬性值,第二個參數為 app 組件自定義屬性值,用戶可以通過方法判斷來返回哪個值,來定義自定義屬性的優先級。
上面代碼定義了如果 mixinVal 有值則返回 mixinValue,否則返回 appVal,所以模板中顯示的應該的是 mixin message
。
局部組件
局部組件的定義,需要顯式聲明進組件內。
// 1. 聲明局部組件變量
const MyMixin = {
data() {
return {
};
},
created() {
console.log('mixin created');
},
methods: {
handleClick() {
},
},
};
// 2. 通過mixins屬性注入到要被混合組件中
const app = Vue.createApp({
mixins: [myMixin]
})
除了需要通過 mixins 屬性注入,其他與全局組件無差異,所以不在單獨闡述。
缺陷
mixin可以將部分組件抽成可重用塊,但是他也有不可避免的問題。
- mixin很容易發生沖突,你會不清晰某個值到底是從 mixin 還是 app 來的。
- 可重用性有限,不能通過傳遞參數修改 mixin 的邏輯,降低了抽象邏輯的靈活性。
總結
這篇文章,我們講了如下幾點:
- mixin的概念及定義
- 混入 data、methods、生命周期函數
- 混入自定義屬性,修改自定義屬性的混合策略
- 全局 mixin 及 局部 mixin 定義方式
- mixin 的缺陷