欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vue-router 源码之实现一个简单的 vue-router

程序员文章站 2022-04-24 07:54:04
前言 通过上篇,我们知道前端理由的两种实现方法,hash 路由与 history 路由,并且用它们分别实现了一个前端路由。 接下来我们就将 vue 与 hash...

前言

通过上篇,我们知道前端理由的两种实现方法,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 呢,先提供一下实现的思路:

  1. 绑定 hashchange 事件,实现前端路由;
  2. 将传入的路由和组件做一个路由映射,切换哪个路由即可找到对应的组件显示;
  3. 需要 new 一个 vue 实例还做响应式通信,当路由改变的时候,router-view 会响应更新;
  4. 注册 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> 标签,点击它便能触发 hashchangerouter-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。

全部源码参考。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。