深入浅析Vue中mixin和extend的区别和使用场景
Vue中有两个较为高级的静态方法mixin和extend,接下来我们来讨论下关于他们各自的原理和使用场景。
Mixin:
原理:
先来看看官网的介绍:
参数:{Object}mixin
用法:
混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的Vue实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。
//为自定义的选项'myOption'注入一个处理器。
Vue.mixin({
created:function(){
varmyOption=this.$options.myOption
if(myOption){
console.log(myOption)
}
}
})
newVue({
myOption:'hello!'
})
//=>"hello!"
我们知道,Vue.mixin传递的这个参数对象,在初始化Vue实例的时候会merge到options上,下面是Vue源码中对mixin的操作。
//src\core\global-api\mixin.js
exportfunctioninitMixin(Vue:GlobalAPI){
Vue.mixin=function(mixin:Object){
this.options=mergeOptions(this.options,mixin)
returnthis
}
}
//src\core\instance\index.js
functionVue(options){
if(process.env.NODE_ENV!=='production'&&
!(thisinstanceofVue)
){
warn('Vueisaconstructorandshouldbecalledwiththe`new`keyword')
}
this._init(options)
}
initMixin(Vue)
...
exportdefaultVue
也就是说,mixin只是对我们在初始化Vue实例时传递的配置对象的一个扩展。
就像上面官网实例写的例子,我们在执行Vue.mixin方法时传递一个配置对象进去,对象里面有个created勾子函数,通过源码我们可以看到这个传递进来的对象最终会和我们在初始化实例也就是newVue(options)时的这个options合并(通过上面源码中的mergeOptions方法),保存在option上。
使用场景:
当我们需要全局去注入一些methods,filter或者hooks时我们就可以使用mixin来做。比如我们希望每一个Vue实例都有一个print方法,我们就可以这么做:
Vue.mixin({
methods:{
print(){
console.log(`我是一个通过mixin注入的方法!`)
}
}
})
或者我们想要去监听在什么阶段时什么组件被加载了,被卸载了等等,我们可以这么做:
Vue.mixin({
mounted(){
console.log(`${this.$route.name}componentmounted!`)
},
destroyed(){
console.log(`${this.$route.name}componentdestroyed!`)
}
})
如果我们并不想给每一个组件实例都混入这些配置options,而只是个别的组件,最好不要使用mixin,它可能会影响到我们组件的性能。
Extend:
原理:
先来看看官网的介绍:
参数:{Object}options
用法:
使用基础Vue构造器,创建一个“子类”。参数是一个包含组件选项的对象。
data选项是特例,需要注意-在Vue.extend()中它必须是函数。
data必须是函数是为了防止各个实例的数据混乱,闭包的应用。
{{firstName}}{{lastName}}aka{{alias}}
', data:function(){ return{ firstName:'Walter', lastName:'White', alias:'Heisenberg' } } }) //创建Profile实例,并挂载到一个元素上。 newProfile().$mount('#mount-point')再来看看源码里面关于Vue.extend的实现:
Vue.extend=function(extendOptions:Object):Function{
extendOptions=extendOptions||{}
constSuper=this
constSuperId=Super.cid
constcachedCtors=extendOptions._Ctor||(extendOptions._Ctor={})
if(cachedCtors[SuperId]){
returncachedCtors[SuperId]
}
constname=extendOptions.name||Super.options.name
if(process.env.NODE_ENV!=='production'&&name){
validateComponentName(name)
}
constSub=functionVueComponent(options){
this._init(options)
}
Sub.prototype=Object.create(Super.prototype)
Sub.prototype.constructor=Sub
Sub.cid=cid++
Sub.options=mergeOptions(
Super.options,
extendOptions
)
Sub['super']=Super
//Forpropsandcomputedproperties,wedefinetheproxygetterson
//theVueinstancesatextensiontime,ontheextendedprototype.This
//avoidsObject.definePropertycallsforeachinstancecreated.
if(Sub.options.props){
initProps(Sub)
}
if(Sub.options.computed){
initComputed(Sub)
}
//allowfurtherextension/mixin/pluginusage
Sub.extend=Super.extend
Sub.mixin=Super.mixin
Sub.use=Super.use
//createassetregisters,soextendedclasses
//canhavetheirprivateassetstoo.
ASSET_TYPES.forEach(function(type){
Sub[type]=Super[type]
})
//enablerecursiveself-lookup
if(name){
Sub.options.components[name]=Sub
}
//keepareferencetothesuperoptionsatextensiontime.
//lateratinstantiationwecancheckifSuper'soptionshave
//beenupdated.
Sub.superOptions=Super.options
Sub.extendOptions=extendOptions
Sub.sealedOptions=extend({},Sub.options)
//cacheconstructor
cachedCtors[SuperId]=Sub
returnSub
}
}
首先我们可以看到,extend方法返回的Sub其实是一个构造函数,而且继承自Vue,也就是说extend方法返回的是Vue的一个子类。
Sub.prototype=Object.create(Super.prototype) Sub.prototype.constructor=Sub
这两行代码其实就是实现Sub对Vue的继承,源码中有一行是
constSuper=this
所以这里的Super指的就是Vue。
Sub.options=mergeOptions( Super.options, extendOptions )
我们注意到在extend中也会对传进来的配置option和Vue原来的options做一个合并。
使用场景:
当我们不需要全局去混入一些配置,比如,我们想要获得一个component。我们可以使用Vue.component(),也可以使用Vue.extend()。
constChildVue=Vue.extend({
...options
})
newChildVue({
...options
})
注意extend得到的是一个Vue的子类,也就是构造函数。
区别:
mixin是对Vue类的options进行混入。所有Vue的实例对象都会具备混入进来的配置行为。
extend是产生一个继承自Vue类的子类,只会影响这个子类的实例对象,不会对Vue类本身以及Vue类的实例对象产生影响。
总结
以上所述是小编给大家介绍的Vue中mixin和extend的区别和使用场景,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!