60行代碼實現一個迷你版Vue Router

這是一個超級精簡版的VueRouter,實現hash模式下,hash改變組件切換的功能,原理就是利用了 Vue.js 的響應式機制觸發router-view組件的從新渲染。html

代碼

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

目錄結構

.
├── index.html
└── myVueRouter.jsgit

路由在模板中的用法應該是下面這樣:github

<!-- 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兩個組件。npm

js中的調用方法是這樣:app

// 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();
  }
}
相關文章
相關標籤/搜索