1、Vue.use( )
源码
源码位置:vue/src/core/global-api/use.js
export function initUse (Vue: GlobalAPI) {
//use方法的参数接收的是一个插件,该插件的类型可以是一个函数,也可以是一个对象
Vue.use = function (plugin: Function | Object) {
//_installedPlugins数组中存放已经安装的插件。
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
//判断一下传递过来的插件是否在installedPlugins中存在,如果存在,则直接返回
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters
//将arguments转换成数组,并且将数组中的第一项去除。
const args = toArray(arguments, 1)
//把this(也就是Vue,这里是通过Vue.use来调用的)插入到数组中的第一个元素的位置。
args.unshift(this)
//这时plugin是一个对象,看一下是否有install这个函数。
if (typeof plugin.install === 'function') {
//如果有install这个函数,直接调用
//这里通过apply将args数组中的每一项展开传递给install这个函数。
// plugin.install(args[0],args[1])
//而args[0],就是上面我们所插入的Vue.这一点与我们前面在模拟install方法的时候是一样的。
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
//如果plugin是一个函数,则直接通过apply去调用
plugin.apply(null, args)
}
//将插件存储到installedPlugins数组中。
installedPlugins.push(plugin)
return this
}
}
2、install方法分析
我们先来看一下vue-router
的目录结构
我们先来核心的文件。
components
目录下面,有两个文件。分别为link.js
和view.js
文件。
link.js
文件创建RouterLink
组件
view.js
文件创建RouterView
组件。
history
目录下的文件是记录路由的历史记录(hash.js
文件是关于hash
模式,html5.js
关于html5
的方式,base.js
公共的内容,abstract.js
是在服务端渲染中实现的路由历史记录)。
index.js
文件是用来创建VueRouter
install.js
文件是关于install
方法
我们自己模拟的VueRouter
也实现上面的目录结构。
下面先来在index.js
文件中实现基本代码。
export default class VueRouter {
//在创建VueRouter对象的时候,会传递选项
constructor(options) {
//获取routes选项,该选项中定义路由规则
this._options = options.routes || [];
}
// 注册路由变化的事件。该方法的参数是一个Vue实例,后期完善
init(Vue) {
}
}
下面实现install.js
基本代码(通过查看源代码来实现)
export let _Vue = null; //将其导出,在其它文件中也可以使用Vue实例,而不需要单独的引入Vue的js文件
export default function install(Vue) {
//获取Vue构造函数
_Vue = Vue;
_Vue.mixin({
//通过混入以后,所有的Vue实例中都会有beforeCreate方法
beforeCreate() {
//判断是否为Vue的实例,如果条件成立为Vue的实例,否则为其它对应的组件(因为在创建Vue实例的时候会传递选项)
if (this.$options.router) {
//通过查看源码发现,Vue的实例会挂在到当前的私有属性_routerRoot属性上
this._routerRoot = this;
this._router = this.$options.router;
//调用index.js文件中定义的init方法
this._router.init(this);
} else {
this._routerRoot = this.$parent && this.$parent._routerRoot;
}
},
});
}
3、组件创建测试
下面需要将install
方法挂载到VueRouter
上。
import install from "./install";
export default class VueRouter {
//在创建VueRouter对象的时候,会传递选项
constructor(options) {
//获取routes选项,该选项中定义路由规则
this._routes = options.routes || [];
}
// 注册路由变化的事件。
init(Vue) {
}
}
//将install方法挂载到VueRouter上
VueRouter.install = install;
下面,我们可以简单实现一下Router-link
组件与Router-view
组件,来做一个简单的测试。(接下来讲解如下内容)
components
目录下的view.js
文件。
export default {
render(h) {
return h("div", "router-view");
},
};
以上是Router-View
组件的基本功能,后面在继续完善。
link.js
文件的实现如下:
export default {
props: {
to: {
type: String,
required: true,
},
},
render(h) {
//通过插槽获取`a`标签内的文本。
return h("a", {
domProps: {
href: "#" + this.to } }, [this.$slots.default]);
},
};
在install.js
文件中,导入上面的组件进行测试。
import View from "./components/view";
import Link from "./components/link";
export let _Vue = null; //将其导出,在其它文件中也可以使用Vue实例,而不需要单独的引入Vue的js文件
export default function install(Vue) {
//获取Vue构造函数
_Vue = Vue;
_Vue.mixin({
//通过混入以后,所有的Vue实例中都会有beforeCreate方法
beforeCreate() {
//判断是否为Vue的实例,如果条件成立为Vue的实例,否则为其它对应的组件(因为在创建Vue实例的时候会传递选项)
if (this.$options.router