VueRouter是组件。
- JavaScript将隔离度控制在了对象,意味着我们可以通过制作一个对象来制作一个框架——Vue就是一个函数对象。
- Vue将隔离度控制在了组件,意味着我们可以通过制作一个组件来制作一个模块——VueRouter就是组件组合的模块。
路由注册
- Vue提供了use方法来注册插件,使用方法:
Vue.use(VueRouter)。 - use源码:
Vue.use = function (plugin) {
// 传入一个plugin,plugin默认为[]。
var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
// 查询该插件是否已经存在
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// 将类数组数据结构转化为真正的数组
var args = toArray(arguments, 1);
// 将this(Vue)将入数组中
args.unshift(this);
// 如果在plugin中定义了install函数,将使用plugin中的install安装Router
// 如果在plugin中没有定义install函数,通过plugin.apply()方法安装Router
// js中apply和call的应用目的——多态——可维护
if (typeof plugin.install === 'function') {
// 在Vue中调用VueRouter的方法,改变VueRouter中的this指向plugin即VueRouter。这是手动多态。
plugin.install.apply(plugin, args);
} else if (typeof plugin === 'function') {
// 如果plugin不存在install方法,调用plugin()函数。
plugin.apply(null, args);
}
// 将已安装的plugin记录在installedPlugins中
installedPlugins.push(plugin);
return this
};
- VueRouter install 源码:
function install (Vue) {
// 如果已经安装该插件,直接返回。
if (install.installed && _Vue === Vue) { return }
// 标志安装
install.installed = true;
// 使用_Vue代理Vue
_Vue = Vue;
// 判断变量v是否初始化
var isDef = function (v) { return v !== undefined; };
// registerInstance做什么的?
var registerInstance = function (vm, callVal) {
var i = vm.$options._parentVnode;
if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
i(vm, callVal);
}
};
// Q:混入这两个做什么?
// 把要混入的对象通过 mergeOption 合并到 Vue 的 options 中
Vue.mixin({
beforeCreate: function beforeCreate () {
if (isDef(this.$options.router)) {
this._routerRoot = this;
this._router = this.$options.router;
this._router.init(this);
Vue.util.defineReactive(this, '_route', this._router.history.current);
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
}
registerInstance(this, this);
},
destroyed: function destroyed () {
registerInstance(this);
}
});
// 访问$router,$route的时候会调用get函数
Object.defineProperty(Vue.prototype, '$router', {
get: function get () { return this._routerRoot._router }
});
Object.defineProperty(Vue.prototype, '$route', {
get: function get () { return this._routerRoot._route }
});
// 注册Vue组件
Vue.component('router-view', View);
Vue.component('router-link', Link);
var strats = Vue.config.optionMergeStrategies;
// use the same hook merging strategy for route hooks
strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
}
总结
Vue 编写的插件要提供静态的 install 方法,通过 Vue.use(plugin) 时候,就是在执行 install 方法。Vue-Router 的 install 方法会给每一个组件注入 beforeCreate 和 destoryed 钩子函数,在 beforeCreate 做一些私有属性定义和路由初始化工作。