60行代码实现一个迷你版Vue Router

这是一个超级精简版的VueRouter,实现hash模式下,hash改变组件切换的功能,原理就是利用了 Vue.js 的响应式机制触发router-view组件的重新渲染。

代码

https://github.com/dora-zc/vue-wheels/tree/master/MiniVueRouter

目录结构

.
├── index.html
└── myVueRouter.js

路由在模板中的用法应该是下面这样:

<!-- index.html -->

<div id="app">
   <router-link to="#/">Home</router-link>
   <router-link to="#/book">Book</router-link>
   <router-link to="#/movie">Movie</router-link>
   <router-view></router-view>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="./myVueRouter.js"></script>

这就需要通过render函数动态生成router-link和router-view两个组件。

js中的调用方法是这样:

// index.html
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', router});

下面是自己实现的超级迷你小路由:

// myVueRouter.js
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);
  }

  // 初始化 hashchange
  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"><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();
  }
}
posted @ 2019-05-17 22:53  dora_zc  阅读(441)  评论(0编辑  收藏  举报