当前位置: 首页 > Web前端 > vue.js

学习vue源码(二)手写Vue.extend方法

时间:2023-03-31 16:49:02 vue.js

Vue.extend(optons);(1)Parameter{object}options(2)Usage使用基本的Vue构造函数创建一个“子类”,其参数是一个“ComponentOptions”对象。data选项是一个特例,在Vue.extend()中,它必须是一个函数。

varProfile=Vue.extend({template:'

{{firstName}}{{lastName}}aka{{alias}}

',data:function(){return{firstName:'Walter',lastName:'White',alias:'Heisenberg'}}})newProfile().$mount('#mount-point');(3)全局API不同于实例方法,是将方法挂载在Vue的原型上,也就是在Vue.原型,而前者直接将方法挂载在Vue上。Vue.extend=function(extendOptions){}(4)Vue.extend的作用是创建一个子类,所以你可以创建一个子类,让它继承一些VueFunction。2.实现(1)创建子类Vue.cid=0letcid=1;Vue.extend=function(extendOptions){扩展选项=扩展选项||{};const超级=这个;//指向Vue构造函数constSuperId=Super.cid;指向Vue构造函数的idconstcachedCtors=extendOptions._Ctor||(extendOptions._Ctor={});if(cachedCtors[SuperId]){返回cachedCtors[SuperId];}constname=extendOptions.name||超级选项名称;if(process.env.NODE_ENV!=='production'){if(!/^[a-zA-Z][\w-]*$/.test(name)){warn('无效的组件名称:"'+name+'".Componentnames'+'只能包含字母数字字符和连字符,'+'并且必须以字母开头。')}}constSub=functionVueComponent(options){this._init(options);}cachedCtors[SuperId]=Sub;returnsub;}1.出于性能考虑,在Vue.extend方法中加入了缓存策略。重复调用Vue.extend实际上应该返回相同的结果。即,如这段代码所示,if(cachedCtors[SuperId]){returncachedCtors[SuperId];那么它是如何判断它们是否相同的呢?让我们举个例子。constobj={template:'

',data:function(){return{}}}varProfile=Vue.extend(obj)varProfile2=Vue.extend(obj)console.log(Profile==Profile2)//true如例子所示,只要obj相同,创建的子类都是相同的。那么如何判断obj,也就是源码中的extendOptions是否是同一个对象呢?这就是这段代码的作用constSuper=this;//指向Vue的构造函数constSuperId=Super.cid;指向Vue的构造函数的id,值为0constcachedCtors=extendOptions._Ctor||(extendOptions._Ctor={});我们将属性_Ctor={}添加到第一个extendOptions作为参数。所以下次我们使用相同的extendOptions创建子类时,extendOptions将具有属性_Ctor。然后赋值cachedCtors[SuperId]=Sub;请注意,cachedCtors指的是extendOptions._Ctor,这意味着它们指向同一个对象。此时extendOptions._Ctor={0:Sub}所以下次会使用同样的extendOptions来判断_Ctor是否已经被缓存。2.name校验,如果发现name选项不合格,会在开发环境中发出警告。3.创建子类并返回。这一步没有继承逻辑。这时候子类就不能用了,不具备Vue的能力。(2)子类继承Vue的能力首先,将父类的原型继承到子类中Sub.prototype=Object.create(Super.prototype);Sub.prototype.constructor=Sub;sub.cid=cid++;1.子类新增cid,代表每个类的唯一标识。将父类的选项继承给子类Sub.options=mergeOptions(Super.options,extendOptions)Sub['super']=Super;1.合并父类options和子类options的逻辑,合并父类Save到子类的super属性。而mergeOptions方法会将两个选项合并到一个新对象中。如果option中有props属性,则对其进行初始化if(Sub.options.props){initProps(Sub);}1.初始化props的作用是将key代理到_props中。例如,vm.name实际上可以访问Sub.prototype._props.name。函数initProps(Comp){constprops=Comp.options.props;for(constkeyinprops){代理(Comp.prototype,'_props',key)}}functionproxy(target,sourceKey,key){sharedPropertyDefinition.get=functionproxyGetter(){returnthis[sourceKey][key];}sharedPropertyDefinition.set=functionproxySetter(val){this[sourceKey][key]=val;}Object.definedProperty(target,key,sharedPropertyDefinition);}ifIfcomputedexistsintheoptions,初始化它if(Sub.options.computed){initComputed(Sub);}functioninitComputed(Comp){constcomputed=Comp.options.计算;for(constkeyincomputed){defineComputed(Comp.prototype,key,computed[key]);}}将父类中存在的属性依次复制到子类中'filter']ASSET_TYPES.forEach(function(type){Sub[type]=Super[type];})if(name){Sub.options.components[name]=Sub;}Sub.superOptions=Super.options;Sub.extendOptions=extendOptions;Sub.sealedOptions=extend({},Sub.options);1.复制到子类的方法有extend、mixin、use、component、directive、filter2。子类上新添加的superOptions、extendOptions和sealedOptions属性总结:创建一个Sub函数,继承父类。如果直接使用Vue.extend,则Sub继承自Vue构造函数。3.完整代码vue.cid=0letcid=1;Vue.extend=function(extendOptions){扩展选项=扩展选项||{};const超级=这个;constSuperId=Super.cid;常量cachedCtors=extendOptions._Ctor||(extendOptions._Ctor={});if(cachedCtors[SuperId]){返回cachedCtors[SuperId];}constname=extendOptions.name||超级选项名称;if(process.env.NODE_ENV!=='production'){if(!/^[a-zA-Z][\w-]*$/.test(name)){warn('无效的组件名称:"'+name+'".Componentnames'+'只能包含字母数字字符和连字符,'+'并且必须以字母开头。')}}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;if(Sub.options.props){initProps(Sub);}if(Sub.options.computed){initComputed(Sub);}Sub.extend=Super.extend;Sub.mixin=Super.mixin'Sub.use=Super.use;ASSET_TYPES.forEach(function(type){Sub[type]=Super[type];})if(name){Sub.options.components[name]=Sub;}Sub.superOptions=Super.options;Sub.extendOptions=extendOptions;Sub.sealedOptions=extend({},Sub.options);cachedCtors[SuperId]=Sub;返回子;}