从vue-router看前端路由实现
我们平常是如何使用vue-router的?
![8e414482b792226dea9cbc729944759f.png](https://i-blog.csdnimg.cn/blog_migrate/7463aeb2f0eedc650cea49f659b3e3a8.jpeg)
![ec6eef2d7a058b6c73b4c158824f962c.png](https://i-blog.csdnimg.cn/blog_migrate/e379c6b4a63d8c6f81091d6c2f1785da.jpeg)
这样三步之后,就可以在任何vue文件中进行路由切换、访问等操作了。那么这三段代码究竟做了什么勒?
先来看一下整体的结构图
![5c4f807248b5616438e01a5eb5c03941.png](https://i-blog.csdnimg.cn/blog_migrate/2211853c6b92f84afea2b46773c51697.jpeg)
- Vue.use方法会调用VueRouter的install函数。主要代码如下:
// 混入,混入对象的选项将混入该组件(vue-router)本身
在install中使用了混入,这样所有的组件都有beforeCreate和destroy的钩子函数,然后给Vue定义了两个属性和两个全局组件。
每个组件在创建时,beforeCreate中传入router实例,然后执行实例的初始化函数,并且定义一个响应式的属性(此类属性值变化时会触发vue实例的重新渲染)。
- 接下来是创建vue-router实例
constructor
根据传入的mode值和对浏览器环境支持的判断,确定要实例化那种类型的history对象(HTML5History或者HashHistory,这里不看abstract部分)。创建时也会声明实例可用的方法如常用的push和replace方法。前面提到的实例的初始化init方法也在这里声明了。
init
这里主要是调用实例的方法。完成根据页面的url值算出对应的router,然后渲染页面,并且添加事件监听,监听url的变化。
然后在来看一下实例化history对象时,又会做些什么。
HashHistory
constructor
它在其中声明了一个setupListener的函数,在里面处理了滚动行为,并且添加事件监听。这个函数在上面的init方法中提到了。它是在transitionTo方法结束完之后执行。(在绑定的事件中也调用了transitionTo方法)。
Html5History
constructor
同样也在开始时处理滚动行为,然后添加监听事件。不同于hashHistory,它是在创建的时候就添加事件监听。
诶,这么说来为什么hash要在回调中监听,不在一创建的时候就添加,何必麻烦?
代码中注释了原因: this is delayed until the app mounts to avoid the hashchange listener being fired too early。避免过早的触发hashchange事件,因为在实例化hashHistory事件的时候会检查url的hash是否是以'/'开头,如果不是,会修改为‘/‘开头,会触发这个事件。
两个类中除了构造器,都定义了实例方法,如果push,replace,go等,在实例化router对象时,也定义了这些方法。router中的方法就是代理的两个history类中的方法。
代码中有个很重要的函数transitionTo,在页面初始化,在监听的事件中都有调用它,那它究竟是什么样的?
transitionTo是基类history定义的方法。
listen
先匹配新的路径,然后调用confirmTransition方法,方法里还有回调函数
confirmTransition
具体细节不太明白,但是看整体是用来创建(调用)路由切换所要执行的钩子函数(导航守卫部分的钩子)。执行完后调用updateRoute方法。
updateRoute
更新实例的current(当前路由),然后调用cb方法,这个方法是在前面的函数中赋值
listen
listen方法是在init的最后调用
// 更新app._route属性,重新渲染页面
所以调用cb方法用于更新vue实例(组件)中的_route响应式属性,从而重新渲染页面。