可以復(fù)用的組件,我們一般會抽離,寫成公共的模塊。
可以復(fù)用的方法,我們一般會抽離,寫成公共的函數(shù)。
那么 在 Vue 中,如果 某幾個組件實例 VueComponent 中、或者 整個 Vue 項目中 都存在相同的配置,那就需要用到 mixin 這個方法了
混入 (mixin) :提供了一種非常靈活的方式,來分發(fā) Vue 組件中的可復(fù)用功能。一個混入對象可以包含任意組件選項。當組件使用混入對象時,所有混入對象的選項將被“混合”進入該組件本身的選項。
?首先、我們需要明白第一點,mixin 是一個對象,而且是包含組件中任意配置項的對象,也就是說,創(chuàng)建組件的時候,我們傳遞的 data、component、methods、computed、directives、生命周期鉤子函數(shù) 等等 一系列配置項 都可以作為 mixin 對象的鍵值對。
其次、我們創(chuàng)建的 mixin 對象,在組件中引用的時候,mixin 對象 中的鍵值對會 混入 該組件的配置詳項中,至于是怎么混入的,下面在講。?
創(chuàng)建 mixin?
?這個 mixin 對象 中,配置了一個 created 鉤子函數(shù),和 methods 對象,如果我們單獨把這個配置寫在組件中的話,那就是組件在初始化的時候,就會調(diào)用 hello()?
// 定義一個混入對象
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
}
}
}
創(chuàng)建一個 mixin 混入對象是很簡單的,只是我們需要注意的是,配置的鍵值對,只能是創(chuàng)建組件時傳入的配置項,如果你傳了一個 其他不存在的屬性 ,組件接收之后,是不會對其解析的,就相當于你在組件內(nèi)部,定義了一個不存在屬性,Vue 底層是不會管這個玩意的。
但是,實例對象上是存在你混入的這個屬性的,下面的自定義混入會說到
const mixin = {
msg: '這是混入的msg',
created: () => {
console.log("mixin混入對象的鉤子被調(diào)用!");
},
};
const vm1 = Vue.extend({
template: `<div>123</div> `,
mixins:[mixin]
})
const vm = new Vue({
el: '#root1',
mixins: [mixin]
})
console.dir(vm1, 'vm1')
console.dir(vm, 'vm')
分別打印出兩個實例對象,左邊是 組件實例對象,右邊是 Vue 實例對象(可以看到其中存在 el 屬性)。我們發(fā)現(xiàn),兩者都是存在混入的數(shù)據(jù)的 ,且混入的自定義數(shù)據(jù)已經(jīng)被平鋪出來了。
使用 mixin 混入?
創(chuàng)建了一個 mixin 對象之后,組件需要使用的時候,就和引入公共組件和公共方法一樣。至于其中的內(nèi)容,還是使用上面定義的
比如:我在 src 目錄下新建了一個 mixin 文件夾,和一個 index.js 文件,那我在引用的時候就正常引入,至于 你是 默認暴露還是分別暴露,那就看個人習慣了。
import {mixin} from '@/mixin/index'
然后在組件配置項中,配置一個 mixins 屬性,值是一個數(shù)組。
export default {
name: 'HelloWorld',
mixins:[mixin]
}
刷新頁面,你會發(fā)現(xiàn)控制臺上已經(jīng)輸出了 我想要的結(jié)果
?mixin 選項合并
?因為 mixin 混入對象 中的配置,是包含組件中任意配置項的對象,如果我的 mixin 混入對象中定義的配置,和組件內(nèi)部定義的配置出現(xiàn)了同名了,那 Vue 是怎么合并這兩個選項的呢?
data數(shù)據(jù)對象:在內(nèi)部會進行遞歸合并,并在發(fā)生沖突時以組件數(shù)據(jù)優(yōu)先
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// => { message: "goodbye", foo: "abc", bar: "def" }
}
})
同名鉤子函數(shù)?:將合并為一個數(shù)組,因此都將被調(diào)用。另外,混入對象的鉤子將在組件自身鉤子?之前?調(diào)用。
export const mixin = {
created: () => {
console.log("mixin混入對象的鉤子被調(diào)用!");
},
};
export default {
name: 'HelloWorld',
mixins: [mixin],
created: function () {
console.log('組件鉤子被調(diào)用')
}
}
?值為對象的選項:例如?methods
、components
?和?directives
,將被合并為同一個對象。兩個對象鍵名沖突時,取組件對象的鍵值對。
export const mixin = {
created: () => {
console.log("mixin混入對象的鉤子被調(diào)用!");
},
methods: {
foo: () => {
console.log("foo");
},
conflicting: () => {
console.log("from mixin");
},
},
};
export default {
name: "HelloWorld",
mixins: [mixin],
created: () => {
console.log("組件鉤子被調(diào)用");
},
methods: {
bar: () => {
console.log("bar");
},
conflicting: () => {
console.log("from self");
},
},
};
在組件中調(diào)用這三個方法,看看在控制臺上輸出的是啥
<div @click="bar">bar</div>
<div @click="conflicting">conflicting</div>
<div @click="foo">foo</div>
?可以看到,mixin 混入對象中存在的 foo 函數(shù),和?conflicting函數(shù),而組件中 存在 bar函數(shù) 和?conflicting 函數(shù)。在組件中能成功調(diào)用這三個方法,說明 mixin 混入對象中的 foo 函數(shù),已經(jīng)被合并到了組件的 methods 對象中。而?conflicting 函數(shù)執(zhí)行之后,根據(jù)打印出的值,發(fā)現(xiàn)該函數(shù)執(zhí)行的是 組件內(nèi)部定義的?conflicting 函數(shù)。這就說明兩個對象鍵名沖突時,取組件對象的鍵值對。
全局混入
上面講的都是在組件內(nèi)部混入,其實也可以在全局中混入。在 mian.js 中,當 執(zhí)行 new Vue ( ) 之前,可以通過?Vue.mixin() 函數(shù),向其內(nèi)部傳入一個 mixin 混入對象,Vue 底層就會將混入對象掛載到Vue全局上。
Vue.mixin({
created: () => {
console.log('我在全局混入了created鉤子函數(shù)');
},
});
new Vue({
render: h => h(App),
}).$mount('#app')
但是這樣存在一個問題,就是如果我在全局通過 Vue.mixin() 混入了配置,那么我所有的組件 (包括第三方組件) 都會混入這個配置,這樣可能會導(dǎo)致組件配置混亂冗余,甚至覆蓋第三方組件的配置導(dǎo)致程序出錯。
?上面我在全局混入了 一個 鉤子函數(shù),導(dǎo)致這個鉤子函數(shù)執(zhí)行了三次,這是因為,在 new Vue() 的時候執(zhí)行了一次,App組件中執(zhí)行了一次,在 HelloWorld 組件也執(zhí)行了一次。這就看出來很多余了。
?自定義混入
區(qū)別:通過 Vue.mixin() 混入的是正?;烊?,直接寫在 new Vue() 中(或者是組件中)的是自定義混入。通過Vue.config.optionMergeStrategies 添加的也是自定義混入
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
new Vue({
myOption: 'hello!'
})
?這里只打印了一次,代表只在 new Vue()的時候執(zhí)行了一次。大多數(shù)情況下,全局的混入只應(yīng)當應(yīng)用于自定義選項,這樣可以避免上面的副作用。
自定義選項將使用默認策略,即簡單地覆蓋已有值。
我先正常混入了一個??myOption 屬性,值為 123。
Vue.mixin({
myOption:'123',
});
打印vm實例,$options 對象中存在該鍵值對
?直接在 new Vue() 中定義 同名屬性,值為 abc
const vm = new Vue({
myOption:'abc',
render: h => h(App),
}).$mount('#app')
打印 vm實例對象,發(fā)現(xiàn)屬性值已經(jīng)更改。
如果想讓自定義選項以自定義邏輯合并,可以向?Vue.config.optionMergeStrategies
?添加一個函數(shù),那我們來看看?Vue.config.optionMergeStrategies
?是個啥
打印出來一看, 好家伙,這不就是 Vue 實例上的所有方法么。按文檔的意思,我好像也可以自定義的往這里面加我自己的方法。
var strategies = Vue.config.optionMergeStrategies;
strategies.myOption = "123";
?我隨便往里面加了一個?myOption 屬性,值為 123,打印出來之后,確實存在設(shè)置的屬性和值
我默認在 new Vue()的時候,注入了一個自定義的選項。這個時候,我們打印這個接收到的vm實例對象,能在 $options 里面找到該屬性,且它的值就是我設(shè)置的 hello
?通過??Vue.config.optionMergeStrategies 添加一個同名的屬性 ,但是這個屬性值是一個函數(shù),且沒有返回值。然后打印vm實例對象會發(fā)現(xiàn) $options 里面的 myOption 屬性值 變成了undefined,函數(shù)沒有返回值,那肯定是undefined。
?增加一個 返回值 abc,再來看看。
上面的例子只是做一個演示,表示這個 也可以 通過??Vue.config.optionMergeStrategies 來覆蓋之前的 自定義 選項,同時還可以讓自定義選項以自定義邏輯合并
Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) {
// 接收兩個參數(shù),返回合并后的值,toVal - 現(xiàn)在定義的值,fromVal - 之前定義的值
console.log(toVal, fromVal, "toVal, fromVal");
return "aaaaaaa";
};
Vue.config.optionMergeStrategies 對象
?Vue.config.optionMergeStrategies 對象 中存在的屬性之前說過了,就是 實例對象上的屬性和方法。那這么多方法 在合并的時候都是怎么合并的呢?這個就需要去源碼里面瞅一瞅了。
總結(jié)
總結(jié):
1、mixin 混入是一個對象,對象的配置項就是 創(chuàng)建組件 時傳入的 options 配置項
2、在組件內(nèi)混入時,增加引入 mixin 對象,配置項中新增 mixins:['xxx']。全局混入時 Vue.mixin()
3、正?;烊? 在組件中新增配置項?或在全局中使用 Vue.mixin()??) 和? 自定義混入的方式( new Vue() 中增加自定義項 或使用?Vue.config.optionMergeStrategies?)還是存在區(qū)別的文章來源:http://www.zghlxwxcb.cn/news/detail-613235.html
4、混入的規(guī)則文章來源地址http://www.zghlxwxcb.cn/news/detail-613235.html
- 普通的js原始值(string,number,boolean等)直接覆蓋,以組件值為主。
- 對象的合并,如果合并雙方都是對象,則使用遞歸的方式將其合并,以組件對象為主。
- 對于函數(shù),如果需要他們合并后都可以執(zhí)行,則可以考慮將函數(shù)合并成數(shù)組,然后你可以將其包裝成一個新函數(shù),依次調(diào)用合并后數(shù)組中的函數(shù)。生命周期鉤子函數(shù)就是這樣,最后是先執(zhí)行混入的鉤子,在執(zhí)行自己的鉤子。
- 如果合并的是一些特殊對象,不能遞歸合并,那么根據(jù)情況,你還可以使用原型鏈的方式進行合并。
到了這里,關(guān)于Vue mixin 混入的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!