hash 模式
URL 中 # 后的地址为路径地址,可以通过 location.url() 去切换路由地址,切换后的地址会被记录在访问记录,如果只改变了 # 后的地址便不会向新地址进行请求。监听 hashchange 事件变化,根据当前地址去请求相应的组件。
history 模式
通过 history.pushState() 方法来改变浏览器地址栏,并把当前地址记录在访问记录。监听 popState事件变化,根据当前地址去请求相应的组件。
实现 vue-router
首先我们来分析一下 vue-router 的工作过程。
下 图 1.1 为 vue-router 的使用过程
首先是注册插件。 我们知道,在 vue.use 函数中,如果传入的参数是一个函数,就会执行这个函数,如果传入的是一个实体对象,就会执行这个对象中的 install 方法。所以这个对象需要一个 install 方法。
再往下看,实例化了一个 VueRouter 对象。所以它应该是一个类或者构造函数。它接收了一个对象形式的参数,里边包含了它的路由规则。由此 我们可以整理出类图如下图 1.2
根据类图来进行 VueRouter 的完成。
首先,因为在 vue.use() 中传入的如果是对象就会调用它的 install 方法,所以我们先进行 install 方法的完成。在 vue.use() 函数调用 install 方法时,会传递两个参数,一个是 vue 的构造数 , 一个是可选的选项对象,我们只实现基本功能,暂时不去考虑第二个参数。
install 函数做了三件事:
1,首先判断当前插件有没有安装,如果安装则不执行后续。
如何判断安装与否呢,我们需要一个变量。首先不能是局部变量,而全局的话,有外部依赖,可能会有影响。
这样显得很尴尬,什么都不行,但是注意, install 是个静态函数,可以视为对象,所以完全可以给它加个属性。
2.把 vue 构造函数记录到全局变量中,因为其他函数可能会用到如 router-link 的重构。
3.把创建 vue 实例时传入的 router 对象 注入到所有 vue 实例上。
如何挂载到所有 vue 实例上,很容易想到,挂载到构造函数上。之前一步我们已经把它记录到了全局中,所以我们接下来只需要拿到 vue 中的配置信息去赋值即可。我们这里可以利用 vue 的混入功能。每一次挂载成功,显然需要我们初始化其他的事件、组件、routeMap
得到具体代码如下图1.3
然后是构造函数,页面初始界面路径为‘/’,所以给 data 的current 赋初值。这里用 vue.observable 来进行动态更新。init 函数没什么好说的,就是为了代码规范,直接一起放出来了。如图1.4
createRouteMap 函数,遍历所有路由规则,把所有规则以键值对的形式,存储到 routeMap 中。
initEvent 函数,主要适用于监听前进后退按钮,对地址栏改变时更新 data 。(触发 popstate 事件) 如图1.5
initComponents 函数,顾名思义,初始化对象中可使用的标签,方便外部使用。我们这里实现一个 router-link 一个 router-view.
router-link 也就是通过 vue.component 去创建一个组件,这组件类似 a 标签,但是因为他不刷新网页,所以拦截一下,阻止他的默认事件,然后跟新地址和 data 中的 current。如图 1.6
顺便说一下 h 函数,render 把标签渲染成节点,h 函数根据信息描述创建 DOM ,接收三个参数,标签名字,标签属性,标签子节点。还有另一种调用方式,直接传入组件。见图1.7.
把 vue 的 vueRouter 替换为我们手写的 vueRouter ,一跑,没问题,撒花 !!✿✿ヽ(°▽°)ノ✿