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

Vue的全局API浅析

时间:2023-03-31 23:16:53 vue.js

/*css*/Vue定义了一些API,然后放在Vue对象上,方便在Vue项目中全局使用Vue.extendVue.extend。Vue.extend的参数是一个组件的选项,然后返回一个用于生成新组件的构造函数。期权的属性是什么?想象一下我们平时写的Vue组件,主要包括模板、数据、方法和生命周期函数。demo可以查看Vue文档,下面是粘贴的源码。functioninitExtend(Vue){/***每个实例构造函数,包括Vue,都有一个唯一的*cid。这使我们能够为原型继承创建包装的“子*构造函数”并缓存它们。*/Vue.cid=0;变种=1;/***类继承*/Vue.extend=function(extendOptions){extendOptions=extendOptions||{};变种超级=这个;varSuperId=Super.cid;varcachedCtors=extendOptions._Ctor||(extendOptions._Ctor={});如果(cachedCtors[SuperId]){returncachedCtors[SuperId]}varname=extendOptions.name||超级选项名称;如果(名称){验证组件名称(名称);}varSub=functionVueComponent(options){this._init(options);};Sub.prototype=Object.create(Super.prototype);Sub.prototype.constructor=Sub;sub.cid=cid++;Sub.options=mergeOptions(Super.options,extendO选项);子['超级']=超级;//对于props和计算属性,我们在扩展时在扩展原型上的//Vue实例上定义代理getter。这//避免为每个创建的实例调用Object.defineProperty。如果(Sub.options.props){initProps$1(Sub);}if(Sub.options.computed){initComputed$1(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;}//在扩展时保留对超级选项的引用。//稍后在实例化时我们可以检查Super的选项是否已经//updated.Sub.superOptions=Super.options;Sub.extendOptions=extendOptions;Sub.sealedOptions=extend({},Sub.options);//缓存构造函数cachedCtors[SuperId]=Sub;返回子};}initExtend函数定义的Vue.extend方法,Vue.cid等于0,即后面代码中的SuperId不变,变量cid表示组件id放在构造函数中,新组件通过自增保持唯一id。直接看Vue.extend对应的方法,extendOptions参数就是上面说的传入的组件options,为了方便我们调用组件参数OPTIONS,此时执行函数super等于this,表示指向Vue,访问OPTIONS中的_Ctor,字面意思同在后面的操作中,可以看出,如果构造函数被缓存,则直接返回。这里我们抱着新建组件构造函数的思路看代码。首先检查OPTIONS中的名称是否符合规范,然后是主体部分,声明组件的构造函数Sub,子类Sub继承父类Vue,然后将构造函数指向回自己,然后定义自己的组件id,和合并选项,定义一个属性super指向Vue。接下来有评论说props和computed是通过代理访问的,然后Vue挂载的方法也是挂载到Sub上……反正很多挂载都是为了方便访问。在定义Sub.sealedOptions属性时,使用了一个extend方法,这个方法与Vue.extend无关,它实现了一个类似于Object.assign的功能。最后执行cachedCtors[SuperId]=Sub,就是把构造函数存放在OPTIONS属性_Ctor中,解释了之前的构造函数缓存,避免重复创建构造函数。结合平时的业务,我们在使用elementUI的消息提示时,直接通过Vue实例上的this.$message方法调用。像弹框一样把组件标签放在组件模板中,通过显示和隐藏来控制,太麻烦了。所以这里举个栗子实现一个加载组件的功能使用/*css*///封装插件方法importVuefrom'vue'importloadingfrom'loadingparameter'constCtor=Vue.extend(loading)//生成构造函数letinstance=nullfunctionLoading(Vue){//这样就完成了在每个VueVue.prototype.$loading={show:function(text){if(!instance){instance=newCtor()instance=instance.$mount()instance.text=text可以在组件实例中使用instance.visible=truedocument.body.appendChild(instance.$el)}else{instance.text=textinstance.visible=true}},hide:function(){if(!instance)返回instance.text=''instance.visible=false}}}exportdefaultLoading最后在main.js中,使用Vue.use注册插件在线演示地址完整项目地址Vue.nextTick对应nextTick方法。Vnode改变后,触发的DOM更新是异步的,以事件循环的方式修改Vnode直到DOM更新完成。这样,如果要访问更新后的DOM,就必须从下一个Tick开始。函数nextTick(cb,ctx){var_resolve;回调。push(function(){if(cb){try{cb.call(ctx);}catch(e){handleError(e,ctx,'nextTick');}}elseif(_resolve){_resolve(ctx);}});如果(!pending){pending=true;定时器功能();}//$flow-disable-lineif(!cb&&typeofPromise!=='undefined'){returnnewPromise(function(resolve){_resolve=resolve;})}}callbacks存储需要执行的回调为下一个滴答声。这里我们看到了两种使用nextTick的形式,一种是回调函数作为nextTick的参数,一种是传递Promise中的resolve方法。pending变量用于控制timerFunc每次只执行一次。可以看到这一系列的操作都是同步的。nextTick执行完之后,timerFunc方法被执行。再看timerFunc,这里是一些兼容性处理,目的是让flushCallbacks方法异步执行。flushCallbacks就是把callbacks中存储的方法取出来,一一执行。这是另一个例子点击上面的按钮后,在第一个nextTick回调中,第1行的输出值应该是content2modification,对应后面的修改值,这在这里也很容易解释。handleNextTick执行后,$nextTick函数的赋值和执行是同步执行的。当msg1被修改时,首先会生成一个异步任务,$nextTick回调函数在第二个异步任务中执行。后面赋值msg2时,因为和msg1在同一个wathcer对象中,所以不会产生新的异步任务。所以当$nextTick回调函数执行时,msg1和msg2对应的DOM已经更新。Vue.set为响应式对象设置响应式属性。知道或者看过Vue源码的都知道,在初始化一个Vue实例的时候,可以通过Object.defineProperty设置对象属性描述符来实现响应式,所以当你直接新增一个属性时,Vue是检测不到的它。看set方法,最后部分defineReactive$$1代表新的属性,这里新的属性不需要采集,直接更新,采集到新的Vnode中即可。vue.delete删除一个属性,直接删除一个属性vue检测不到。该文件还说你应该很少使用它。如果要触发响应,也可以直接将属性赋值为null或undefined。vue.directive自定义指令可以减少写一些重复的代码,不好说。查看文档,结合源码中v-model的封装方式。vue.filter过滤器,这个用起来比较简单,因为看demo就可以了。Vue源码中,使用ASSET_TYPES数组保存组件、指令、过滤器三个字符串。这三种方法注册特殊点。Vue.component通常用于全局注册组件。其实这个方法所做的就是生成组件构造函数。该方法的第一个参数是组件名称;第二个参数是组件选项(如果第二个参数为空,则返回组件名称的构造函数)。注册时使用Vue.extend返回组件的构造函数,保存在Vue.options.components对象中,使用组件名访问key值。Vue.use用于安装Vue插件的方法。它接受函数或对象插件。如果它是一个对象,它必须有一个安装方法。如果它是一个函数,它将作为安装方法执行。Vue会在调用passin的时候作为第一个参数。函数initUse(Vue){Vue.use=function(plugin){varinstalledPlugins=(this._installedPlugins||(this._installedPlugins=[]));if(installedPlugins.indexOf(plugin)>-1){returnthis}//附加参数varargs=toArray(arguments,1);args.unshift(这个);if(typeofplugin.install==='function'){plugin.install.apply(plugin,args);}elseif(typeofplugin==='function'){plugin.apply(null,args);}installedPlugins.push(插件);返回这个};查看源码,Vue中会定义一个_installedPlugins数组来控制每个插件只注册一次。unshift将Vue添加到第一个参数。plugin方法执行后,会存储在_installedPlugins中,最后返回给Vue,这样Vue.use就可以像这样链式使用:Vue.use(plugin1).use(plugin2)。Vue.mixin全局混入方法或者属性,因为变化的是Vue.options,会合并到所有的Vue实例中,所以每个组件都可以访问。比如我们的vue-router和vuex全局混入beforeCreate周期函数,然后在周期函数的执行中加入$router和$store属性,让每个组件都可以访问到。Vue.compile官方解释:将模板字符串编译成render函数,完整版才有。我:这里就不分析了,理解不深。Vue.observable使一个对象响应式,查看源码Vue.observable=function(obj){observe(obj);返回对象};可以看到和初始化组件一样,observe是用来让对象响应的。这里也用一个小栗子来演示。Vue.version返回Vue版本号以上是对Vue文档中全局API的简单分析。