vue-router 源码之实现一个简单的 vue-router
前言
通过上篇,我们知道前端理由的两种实现方法,hash 路由与 history 路由,并且用它们分别实现了一个前端路由。
接下来我们就将 vue 与 hash 路由结合,实现一个非常简单的 vue-router 吧。
开始实现
想象一下,如果自己实现了一个 vue-router,会怎么去使用呢?参考 vue-router 官方的使用方式,看看 html 的使用:
<div id="app"> <p> <router-link to="#/">home</router-link> <router-link to="#/book">book</router-link> <router-link to="#/movie">movie</router-link> </p> <router-view></router-view> </div>
这里会有 router-link 和 router-view 两个组件需要我们来实现。再来看 js 的:
const home = { template: '<div>home</div>' }; const book = { template: '<div>book</div>' }; const movie = { template: '<div>movie</div>' }; const routes = [ { path: '/', component: home }, { path: '/book', component: book }, { path: '/movie', component: movie } ]; const router = new vuerouter(vue, { routes }); new vue({ el: '#app' });
这里会有我们自己定义的组件 home、book 和 movie,并且有它们各自对应的路由。我们实现的 vuerouter 跟官方的有些区别,在 vuerouter 被 new 时是将 vue 作为参数传入,而不是注入挂载到根实例下。
接下来就是 vuerouter 的实现了。
vuerouter
要怎么来实现 vuerouter 呢,先提供一下实现的思路:
- 绑定 hashchange 事件,实现前端路由;
- 将传入的路由和组件做一个路由映射,切换哪个路由即可找到对应的组件显示;
- 需要 new 一个 vue 实例还做响应式通信,当路由改变的时候,router-view 会响应更新;
- 注册 router-link 和 router-view 组件。
先创建一个 vuerouter:
class vuerouter { constructor (vue, options) { this.$options = options; } }
绑定事件
给 vuerouter 添加一个绑定事件的方法,一旦路由发生改变,会触发 onhashchange
方法。
constructor (vue, options) { this.init(); } // 绑定事件 init () { window.addeventlistener('load', this.onhashchange.bind(this), false); window.addeventlistener('hashchange', this.onhashchange.bind(this), false); }
路由映射表
将传入的 options 设置成一张路由映射表,以便于通过路由查找到对应的组件。
constructor (vue, options) { this.$options = options; this.routemap = {}; this.createroutemap(this.$options); } // 路由映射表 createroutemap (options) { options.routes.foreach(item => { this.routemap[item.path] = item.component; }); }
options 之中,路由与组件的关系:
const routes = [ { path: '/', component: home }, { path: '/book', component: book }, { path: '/movie', component: movie } ];
生成的路由映射表:
this.routemap = { '/': home, '/book': book, '/movie': movie };
响应
我们需要 new 一个新的 vue 实例,将当前路由 current 储存在其 data 之中,当修改了 current 时,router-view 就会自己去更新视图。
constructor (vue, options) { this.app = new vue({ data: { current: '#/' } }); } // 获取当前 hash 串 gethash () { return window.location.hash.slice(1) || '/'; } // 设置当前路径 onhashchange () { this.app.current = this.gethash(); }
只要在 router-view
里使用到了 this.app.current
,一旦更新它,便会更新。
注册组件
router-link
实际上就是一个 <a> 标签,点击它便能触发 hashchange
。router-view
会实现一个 render 方法,将当前路由对应的组件取出,进行渲染。
constructor (vue, options) { this.initcomponent(vue); } // 注册组件 initcomponent (vue) { vue.component('router-link', { props: { to: string }, template: '<a :href="to" rel="external nofollow" rel="external nofollow" ><slot></slot></a>' }); const _this = this; vue.component('router-view', { render (h) { var component = _this.routemap[_this.app.current]; return h(component); } }); }
完整代码
至此,一个简单的 vue-router 就出来了,全部代码是这样的:
class vuerouter { constructor (vue, options) { this.$options = options; this.routemap = {}; this.app = new vue({ data: { current: '#/' } }); this.init(); this.createroutemap(this.$options); this.initcomponent(vue); } // 绑定事件 init () { window.addeventlistener('load', this.onhashchange.bind(this), false); window.addeventlistener('hashchange', this.onhashchange.bind(this), false); } // 路由映射表 createroutemap (options) { options.routes.foreach(item => { this.routemap[item.path] = item.component; }); } // 注册组件 initcomponent (vue) { vue.component('router-link', { props: { to: string }, template: '<a :href="to" rel="external nofollow" rel="external nofollow" ><slot></slot></a>' }); const _this = this; vue.component('router-view', { render (h) { var component = _this.routemap[_this.app.current]; return h(component); } }); } // 获取当前 hash 串 gethash () { return window.location.hash.slice(1) || '/'; } // 设置当前路径 onhashchange () { this.app.current = this.gethash(); } }
最后
将 vue 与 hash 路由结合,监听了 hashchange 事件,再通过 vue 的 响应机制 和 组件,便有了上面实现好了一个 vue-router。
全部源码参考。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
vue-router源码之history类的浅析
-
使用.Net Core + Vue + IdentityServer4 + Ocelot 实现一个简单的DEMO +源码
-
vue-router 源码实现前端路由的两种方式
-
Android下实现一个简单的计算器源码
-
vue-router 源码之实现一个简单的 vue-router
-
使用.Net Core + Vue + IdentityServer4 + Ocelot 实现一个简单的DEMO +源码
-
vue-router 源码实现前端路由的两种方式
-
撸一个简单的vue-router来剖析原理
-
vue全家桶(vue-router简版源码的实现)
-
Android下实现一个简单的计算器源码