mixin, 外部的對象能混入到 app 執行個體的操作
本篇開始來學習一波 vue 中的一些複用性代碼的基礎操作, 首先來介紹關于代碼 "混入" mixin 的寫法. 直覺了解這個 mixin 就是一個 js 對象去 "混入" vue 的元件呀, 插件呀之類的片段中.
mixin 直覺認識
<!DOCTYPE html>
<html lang="en">
<head>
<title>mixin 混入</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
// mixin 對象混入
const myMixin = {
data () {
return { num: 999 }
}
}
const app = Vue.createApp({
data () {
return { num: 666, youge:"nb" }
},
// 其實就是在 vue 之外定義的一段代碼, 通過 mixins 屬性混進來
mixins: [myMixin],
template: `
<div>
<div>{{num}} - {{youge}}</div>
</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
上述代碼即我們在 vue 的外面定義了一個叫 myMixin 的對象, 裡面也有一個 data ( ) 的方法. 然後将其整個通過 vue 執行個體 app 的 mixins 屬性成功 "混入" 了進來. 這個其實就是混入的概念呀.
值得注意的是, 屬性發生沖突時, 如這裡的元件 data 和 混合 data 沖突, 或者 methods 沖突, 元件屬性的優先級會高于 mixin 的優先級.
生命周期函數混入
和 data ( ) 是相反的, 會先執行 mixin, 後執行元件的.
<!DOCTYPE html>
<html lang="en">
<head>
<title>mixin 混入</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
// mixin 對象混入
const myMixin = {
data () {
return { num: 999, youge:"nb" }
},
// 生命周期函數先執行 mixin, 後執行元件的
created () {
console.log('mixin created')
}
}
const app = Vue.createApp({
data () {
return { num: 666 }
},
mixins: [myMixin],
// 元件的生命周期函數會被後執行
created () {
console.log('app created')
},
template: `
<div>
<div>{{num}} - {{youge}}</div>
</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
這種在 vue 之外定義的對象, 通過 mixins 屬性可以實作最外層的混入. 但如果有子元件的存在, 則子元件就不能使用這個 mixin 因為它是局部的, 就和之前局部元件和全局元件一樣. 如果一定要使用, 則可以在子元件中進行 mixin, 這就略有一丢麻煩
<!DOCTYPE html>
<html lang="en">
<head>
<title>子元件用 mixin</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const myMixin = {
data () {
return { num: 999, youge:"nb" }
},
}
const app = Vue.createApp({
data () {
return { num: 666 }
},
mixins: [myMixin],
created () {
console.log('app created')
},
template: `
<div>
<div>{{num}} - {{youge}}</div>
<Son />
</div>
`
})
// 子元件不能直接用父元件的 mixin, 隻能自己來進行混入
app.component('Son', {
mixins: [myMixin],
template: `<div>son-{{youge}}</div>`
})
const vm = app.mount('#root')
</script>
</body>
</html>
可以發現這樣寫 mixin 其實是一個局部的, 一次定義多次引用, 這個沒啥問題, 但基于咱對這種 vue 的父子元件來說, 感覺還是有點怪怪的, 理想中, 這個這個 mixin 都混入父元件了, 為啥子元件還不能直接引用, 額, 它就是不能.
當然, 我們還通過注冊全局 mixin 來實作它.
<!DOCTYPE html>
<html lang="en">
<head>
<title>全局 mixin</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
data() {
return { num: 666 }
},
created() {
console.log('app created')
},
template: `
<div>
<div>{{num}} - {{youge}}</div>
</div>
`
})
// 注冊全局 mixin 所有元件自動注入
app.mixin({
data() {
return { num: 999, youge: "nb" }
},
created() {
console.log('mixin created')
}
})
const vm = app.mount('#root')
</script>
</body>
</html>
則通過 app.mixin ({ }) 的寫法就将這個這個 mixin 對象全局混入了. 但是呢這種寫法不推薦, 這和全局元件一樣的, 一個是維護上的問題, 一個是性能上的問題啦.
自定義屬性
在預設情況下, 元件中的屬性優先級高于 mixin 中的屬性, 其示範如下:
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定義屬性</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const myMixin = {
num: 666
}
const app = Vue.createApp({
mixins: [myMixin],
num: 999,
template: `
<div>
<div>{{this.$options.num}}</div>
</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
注意在 vue 執行個體中, 所有的屬性最終都會挂載到 $options 中, 隻不過我們常用的 data, methods, template ... 等已經有内置了就直接對應上啦. 那對于其他的就是挂載到最外層呀.
但 vue 也提供了對于這種自定義屬性的合并政策是可以自定義的, 比如我們就要讓 mixin 的屬性優先級高于元件, 則可以通過 app.config.optionMergeStrategies.xxx 的方式進行配置即可.
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定義屬性的優先配置</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const myMixin = {
num: 666
}
const app = Vue.createApp({
mixins: [myMixin],
num: 999,
template: `
<div>
<div>{{this.$options.num}}</div>
</div>
`
})
// 編寫 自定義屬性 的優先政策配置
app.config.optionMergeStrategies.num = (mixinValue, appValue) => {
return mixinValue || appValue
}
const vm = app.mount('#root')
</script>
</body>
</html>
但基于 vue3 的新特性, 其實這種 mixin 的寫法相對少了很多, 更多則會有 CompositonAPI 的方式來做替換會顯得更加強大和靈活啦.
小結
- mixin 混入的意思就是在 vue 執行個體之外的對象可以通過 app 的 mixins 屬性混入 vue 中來管理使用
- 元件 data, methods 的優先級高于 mixin , 即隻會顯示一個
- 生命周期函數 mixin 的優先級高于元件, 會依次調用
- 自定義屬性的元件優先級高于 mixin, 但可通過 app.config.optionMergeStrategies.xxx 進行配置