1.vue-router源码下载
我们可以到github上找到对应版本的vue-router
版本号可以到项目中的node_modules/vue-router/dist/vue-router.js查看嘴上面的许可证说明(package.json只提供了版本的大致范围 ^表示2.2.x 而~表示2.x.x 都为>=的含义)
在github上的vue-router我们要选择Tags中的版本号去下载 而非Branches(这是开发版本 不稳定)
2.源码分析
通过IDE打开刚刚下载好的源码 进入之后 我们选择src/index.js(src下的核心文件) 不断往上溯源 可以找到一个router.js 其中内置了一个install方法(每一个vue插件在使用之前都需要通过use方法进行插件的下载 use方法内部内置了install方法用于下载vue插件)
我们可以通过ctrl+单词的方式查看install定义的源码 从里面我们可以看到两个很熟悉的组件的全局注册 即RouterLink和RouterView 他们可以用于进行路由跳转和路由页面展示位置的确定 并且vue文件的命名一般遵循大驼峰命名 而组件的使用则遵循短横线命名 其中肯定是存在着大驼峰->段横向的变换机制
除了两个组件的注册之外 我们还可以看到我们分析的重点–$router/$route
3.前置知识
① js对象中属性的设置 除了说可以通过内置定义来完成 还可以通过调用相关的api完成 格式为Object.defineProperty(类名.prototype, 属性名, 属性值)
其中类名.prototype
获取的是该类名对应的原型对象
② 每一个组件都会继承自Vue原型对象 从而拿到他的变量/方法进行使用
4.$router/$route源码分析
在install.js文件中
通过上述两个方法完成了对$router/$route的赋值操作
其中 通过defineProperty方法对Vue原型对象中的$router/$route进行赋值操作
我们分别来看一下两个变量的赋值过程:
1.$router的赋值
其实他的赋值操作可以看待成Vue.prototype.$router = return this._routerRoot._router(这种写法不严谨)
返回值其实是通过上文中这个函数定义的 其中 他会先去判断一下Vue实例中是否传递了options对象($options对应的就是Vue实例中的options对象) 如果有的话 那么就执行里面的逻辑 其中 this指针表示mixin作用域中的this指针(他指向的是他的调用者 即Vue) 首先 他将Vue中的_routerRoot赋值为了本身 接着将Vue中的_router赋值为options对象中的router(挂载到Vue实例中的router对象 即导入的VueRouter实例)
而返回值this.\_routerRoot.\_router
中的this._routerRoot
表示的是第一个赋值操作的Vue 而this.\_routerRoot.\_router
则表示Vue.\_router
即第二个赋值操作中的this.$options.router 即为Vue实例中挂载的router
2.$route的赋值
他的赋值操作可以看作Vue.prototype.$route = return this._routerRoot._route(该写法也不严谨)
我们来分析一下返回值this._routerRoot._route
该返回值其实是动态变化的 他是根据用户的路由选择来决定取值的 他指向的是正处于活跃状态的路由
5.组件中$router/$route的可行性
那么既然我们已经从源码中知道了Vue原型对象中存在$router/$route以及他们的由来
那么他们是如何将这两个变量共享到每一个组件当中的呢
通过前面的前置知识 你就可以知道 每一个组件都会继承自Vue的原型对象 从而拿到他内置的变量/方法去使用 正因为如此 所有的组件才都能够访问$router/$route这两个变量
6.api分析
在我们vue-router源码中 src目录下的router.js文件中 内置了VueRouter的定义类 类中定义了多个常见的api 比如我们所熟悉的push、replace、go等等之类的方法
结合我们之前的分析 Vue原型对象/组件中共享了$router 他指向了正是这个VueRouter对象 所以说我们可以通过$router去调用router.js文件中内置的大量方法