vue中提供了一種混合機制--mixins,用來更高效的實現(xiàn)組件內(nèi)容的復用。最開始我一度認為這個和組件好像沒啥區(qū)別。。后來發(fā)現(xiàn)錯了。下面我們來看看mixins和普通情況下引入組件有什么區(qū)別?
mixins
混合 (mixins) 是一種分發(fā) Vue 組件中可復用功能的非常靈活的方式。
混合對象可以包含任意組件選項。
當組件使用混合對象時,所有混合對象的選項將被混入該組件本身的選項。
mixins理解
組件在引用之后相當于在父組件內(nèi)開辟了一塊單獨的空間,來根據(jù)父組件props過來的值進行相應的操作,單本質上兩者還是涇渭分明,相對獨立。
而mixins則是在引入組件之后,則是將組件內(nèi)部的內(nèi)容如data等方法、method等屬性與父組件相應內(nèi)容進行合并。相當于在引入后,父組件的各種屬性方法都被擴充了。
- 單純組件引用:
父組件 + 子組件 >>> 父組件 + 子組件 - mixins:
父組件 + 子組件 >>> new父組件
有點像注冊了一個vue的公共方法,可以綁定在多個組件或者多個Vue對象實例中使用。另一點,類似于在原型對象中注冊方法,實例對象即組件或者Vue實例對象中,仍然可以定義相同函數(shù)名的方法進行覆蓋,有點像子類和父類的感覺。
mixins的使用
方法的復用
html
<div id="app">
<child></child>
<kid></kid>
</div>
js
Vue.component('child',{
template:`<h1 @click="foo">child component</h1>`,
methods:{
foo(){
console.log('Child foo()'+this.msg++)
}
}
})
Vue.component('kid',{
template:`<h1 @click="foo">kid component</h1>`,
methods:{
foo(){
console.log('Kid foo()'+this.msg++)
}
}
})
在借助mixins之前,在兩個不同的組件的組件中調用foo方法,需要重復定義,倘若方法比較復雜,代碼將更加冗余。若借助mixins,則變得十分簡單:
let mixin={
data(){
return{
msg:1
}
},
methods:{
foo(){
console.log('hello from mixin!----'+this.msg++)
}
}
}
var child=Vue.component('child',{
template:`<h1 @click="foo">child component</h1>`,
mixins:[mixin]
})
Vue.component('kid',{
template:`<h1 @click="foo">kid component</h1>`,
mixins:[mixin]
})
雖然此處,兩個組件用可以通過this.msg引用mixins中定義的msg,但是,小編嘗試過,兩個組件引用的并不是同一個msg,而是各自創(chuàng)建了一個新的msg。如果在組件中定義相同的data,則此處會引用組件中的msg,而非mixins中的。
方法的覆蓋
如果在引用mixins的同時,在組件中重復定義相同的方法,則mixins中的方法會被覆蓋。
var child=Vue.component('child',{
template:`<h1 @click="foo">child component</h1>`,
mixins:[mixin],
methods:{
foo(){
console.log('Child foo()'+this.msg++)
}
}
})
此時,若單擊h1標簽,則在控制臺中打印"Child foo() 1" 3、合并生命周期此時,若單擊h1標簽,則在控制臺中打印"Child foo() 1"
合并生命周期
let mixin={
mounted(){
console.log('mixin say hi')//先輸出
},
data(){
return{
msg:1
}
},
methods:{
foo(){
console.log('mixin foo()'+this.msg++)
}
}
}
let vm=new Vue({
el:"#app",
data:{
msg: 2
},
mounted: function(){
console.log('app say hi')//后輸出
},
methods:{
foo(){
console.log('Parent foo()'+this.msg)
}
}
})
通過上面的介紹,現(xiàn)在對mixins有了比較深入的了解,在設計復雜組件時是很有必要的。
實踐:狀態(tài)碼統(tǒng)一過濾
一般情況下不要全局使用,因為會污染vue所有實例,這里通過一個簡單的應用展示mixin的使用技巧,在所有vue實例中添加統(tǒng)一狀態(tài)碼過濾器。
因為自定義方法會在所有的實例中混入,如果按照以前的方法,難免會有覆蓋原先的方法的危險,按照官方的建議,混入的自定義方法名增加前綴 $_ 用作區(qū)分。
創(chuàng)建一個 config.js 文件,用于保存狀態(tài)碼對應的含義,將其暴露出去
export const typeConfig = {
1: "type one",
2: "type two",
3: "type three"
}
再創(chuàng)建一個 filters.js 文件,用于保存所有的自定義函數(shù)
import { typeConfig } from "./config"
export default {
filters: {
$_filterType: (value) => {
return typeConfig[value] || "type undefined"
}
}
}
最后,在 main.js 中引入我們的 filters 方法集
import filter from "./filters"
Vue.mixin(filter)
接下來,我們就可以在 .vue 的模板文件中隨意使用自定義函數(shù)了
<template>
<div>{{typeStatus | $_filterType}}<div>
</template>
包裝插件
接下來簡單應用一下 Vue 中插件的制作方法。創(chuàng)建插件之后,就可以 Vue.use(myPlugin) 來使用了。
首先附上插件的 官方文檔[點我查看]。
一句話解釋,包裝的插件需要一個 install 的方法將插件裝載到 Vue 上。
關于 Vue.use() 的源碼
function initUse (Vue) {
Vue.use = function (plugin) {
var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters
var args = toArray(arguments, 1);
args.unshift(this);
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args);
} else if (typeof plugin === 'function') {
plugin.apply(null, args);
}
installedPlugins.push(plugin);
return this
};
}
很直觀的就看到他在最后調用了 plugin.install 的方法,我們要做的就是處理好這個 install 函數(shù)即可。
config.js 文件依舊需要,這里保存了所有狀態(tài)碼對應的轉義文字
創(chuàng)建一個 myPlugin.js 文件,這個就是我們編寫的插件
import { typeConfig } from "./config"
myPlugin.install = (Vue) => {
Vue.mixin({
filters: {
$_filterType: (value) => {
return typeConfig[value] || "type undefined"
}
}
})
}
export default myPlugin
插件的 install 函數(shù)的第一個參數(shù)為 Vue 的實例,后面還可以傳入一些自定義參數(shù)。
在 main.js 文件中,我們不用 Vue.mixin() 轉而使用 Vue.use() 來完成插件的裝載。
import myPlugin from "./myPlugin"
Vue.use(myPlugin)
至此,我們已經(jīng)完成了一個小小的插件,并將我們的狀態(tài)碼轉義過濾器放入了所有的 Vue 實例中,在 .vue 的模板文件中,我們可以使用 {{ typeStatus | $_filterType }} 來進行狀態(tài)碼轉義了。
Vue.mixin() 可以將自定義的方法混入所有的 Vue 實例中,謹慎使用。