浅谈vue.use()方法从源码到使用
关于vue.use我们都知道些什么?
在做vue开发的时候大家一定经常接触Vue.use()方法,官网给出的解释是:通过全局方法Vue.use()使用插件;我觉得把使用理解成注册更合适一些,首先看下面常见的注册场景。
importRouterfrom'vue-router' Vue.use(Router) importVuexfrom'vuex' Vue.use(Vuex) importEchartsfrom'echarts' Vue.prototype.$echarts=Echarts
关于echarts的注册很简单,直接挂在Vue方法的原型上,通过原型链继承的关系可以在任意一个组件里通过this.$echarts访问到echarts实例,我们来写一个简单的例子证明一下。
functionmyVue(title){ this.title=title } myVue.prototype.myUse='在原型上添加公共属性' constA=newmyVue('我是实例A') constB=newmyVue('我是实例B') console.log(A.title,B.title,A.myVue,B.myVue,) //我是实例A我是实例B在原型上添加公共属性在原型上添加公共属性
而Router和Vuex的注册就要去分析Vue.use()的源码了,在分析源码之前先总结一下官方对Vue.use()方法的说明:
- 通过全局方法Vue.use()使用插件
- Vue.use会自动阻止多次注册相同插件
- 它需要在你调用newVue()启动应用之前完成
- Vue.use()方法至少传入一个参数,该参数类型必须是Object或Function,如果是Object那么这个Object需要定义一个install方法,如果是Function那么这个函数就被当做install方法。在Vue.use()执行时install会默认执行,当install执行时第一个参数就是Vue,其他参数是Vue.use()执行时传入的其他参数。
官网说Vue.use()是用来使用插件的,那么传入的Router和Vuex就是这里指的插件,而这个插件本质上又是一个install方法。至于install方法内部实现了什么逻辑就由插件自身的业务决定了。
源码分析
首先说一下Flow,vue源码中那些奇怪的写法Vue.use=function(plugin:Function|Object)是Flow的语法,Flow是facebook出品的JavaScript静态类型检查工具。JavaScript是动态类型语言,它的灵活性有目共睹,但是过于灵活的副作用是很容易就写出非常隐蔽的隐患代码,在编译期甚至看上去都不会报错,但在运行阶段就可能出现各种奇怪的bug。
下面我们正式开始分析源码,Vue.use()的源码很简单30行都不到,首先看src/core/global-api/use.js下Vue.use()方法的定义:
import{toArray}from'../util/index' exportfunctioninitUse(Vue:GlobalAPI){ Vue.use=function(plugin:Function|Object){ constinstalledPlugins=(this._installedPlugins||(this._installedPlugins=[])) if(installedPlugins.indexOf(plugin)>-1){ returnthis } constargs=toArray(arguments,1) args.unshift(this) if(typeofplugin.install==='function'){ plugin.install.apply(plugin,args) }elseif(typeofplugin==='function'){ plugin.apply(null,args) } installedPlugins.push(plugin) returnthis } }
上面源码中使用了工具函数toArray,该函数定义在src/shared/util.js
exportfunctiontoArray(list:any,start?:number):Array{ start=start||0 leti=list.length-start constret:Array =newArray(i) while(i--){ ret[i]=list[i+start] } returnret }
了解一下源码实现了什么逻辑
Vue.use=function(plugin:Function|Object){
在全局apiVue上定义了use方法,接收一个plugin参数可以是Function也可以是Object,这就和前面官方规定的Vue.use()第一个参数要求的类型对应上了。
if(installedPlugins.indexOf(plugin)>-1){
用来判断该插件是不是已经注册过,防止重复注册。
constargs=toArray(arguments,1)
arguments是Vue.use()方法的参数列表是一个类数组,后面的1先理解成一个常量,toArray方法的作用就是把第一个Array参数从下标为1截取到最后。也就拿到了Vue.use()方法除去第一个之外的其他参数,这些参数准备在调用instll方法的时候传入。
if(typeofplugin.install==='function'){
}elseif(typeofplugin==='function'){
这里的if语句是判断Vue.use()传入的第一个参数是Object还是Function。
plugin.install.apply(plugin,args)
plugin.apply(null,args)
判断完之后执行那个对应的install方法,用apply改变this指向,并把toArray得到的剩余参数传入。
installedPlugins.push(plugin)
最后记录该组件已经注册过了
现在我们发现Vue.use()的注册本质上就是执行了一个install方法,install里的内容由开发者自己定义,通俗讲就是一个钩子可能更贴近语义化而已。
Vue.use()有什么用
在install里我们可以拿到Vue那么和Vue相关的周边工作都可以考虑放在Vue.use()方法里,比如:
- directive注册
- mixin注册
- filters注册
- components注册
- prototype挂载
- ...
echarts用Vue.use()来注册
main.js
importVuefrom'vue' importechartsfrom'./echarts.js' Vue.use(echarts) newVue({ ... })
echarts.js
importEchartsfrom'echarts' exportdefault{ install(Vue){ Vue.prototype.$echarts=Echarts } }
这样写的好处是可以在install的文件里做更多配置相关的工作,main.js不会变的臃肿,更方便管理。
全局组件用Vue.use()来注册
base.js
importafrom'./a' importbfrom'./b' letcomponents={a,b} constinstallBase={ install(Vue){ Object.keys(components).map(key=>Vue.component(key,components[key])) } }
main.js
importVuefrom'vue' importbasefrom'./base.js' Vue.use(base) newVue({ ... })
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。