vue系列--實現一個簡單的vue-router

一個簡單的vue的路由實現

1. 聲明類

class SimpleVueRouter {}

2. 註冊install方法,接收Vue類

SimpleVueRouter.install = function(_Vue) {
  // Vue是js內部的變量,_Vue是真正的Vue類
  Vue = _Vue;
}

3. 寫SimpleVueRouter的構造函數,保存傳進來的路由配置options,聲明一個路由對應關係,聲明一個Vue的實例對象用於響應式

class SimpleVueRouter {
  constructor(options) {
    this.$options = options;

    this.routeMap = {};

    this.app = new Vue({
      data() {
        return {
          current: '/'
        }
      }
    });
  }
}

4. 在SimpleVueRouter類裏新增init方法,在install方法裏給Vue註冊mixin,給Vue加上$router和執行init方法

// 添加install方法,在Vue.use的時候會執行
SimpleVueRouter.install = function(_Vue) {
  Vue = _Vue;
  Vue.mixin({
    beforeCreate() {
      /**
       * this是Vue的實例對象
       * this.$options是new Vue()的時候傳入的參數
       * 只有main.js纔會有router這個項,因此if只會進入一次
       *  */ 
      if (this.$options.router) {
        this.$router = this.$options.router;
        this.$options.router.init();
      }
    }
  });
}

5. 監聽瀏覽器的hashChange和load方法事件,當監聽到的時候,修改this.app.current

initEvent() {
    // 監聽瀏覽器的hashchange和load事件,使用bind改變this指向
    window.addEventListener('hashchange', this.handleHashChange.bind(this));
    window.addEventListener('load', this.handleHashChange.bind(this));
  }

  handleHashChange() {
    // 獲取#後面的部分賦值給app的current
    this.app.current = location.hash.slice(1);
  }

6. 註冊路由對應關係

initRouteMap() {
    this.$options.routes.forEach(item => {
      this.routeMap[item.path] = item;
    });
  }

7. 註冊s-router-link和s-router-view組件

registerComponents() {
    Vue.component('s-router-link', {
      props: {
        to: String
      },
      render: function (h) {
        return h('a', { attrs: { href: `#${this.to}` } }, this.$slots.default);
      }
    });

    Vue.component('s-router-view', {
      render: h => {
        // 此處使用箭頭函數,爲了讓this指向當前router實例而不是vue實例
        const com = this.routeMap[this.app.current].component;
        return h(com)
      }
    });
  }

8. 在init方法裏分別初始化事件、路由和組件

init() {
    this.initEvent();
    this.initRouteMap();
    this.registerComponents();
  }

9. 使用方法

import SimpleVueRouter from './simple-vue-router';
import Vue from 'vue';
import Com1 from './components/com1';
import Com2 from './components/com2';
import Home from './components/home';

Vue.use(SimpleVueRouter);

export default new SimpleVueRouter({
  routes: [{
    path: '/',
    component: Home
  }, {
    path: '/com1',
    component: Com1
  }, {
    path: '/com2',
    component: Com2
  }]
});
<template>
  <div id="app">
    <s-router-link to="/com1">com1</s-router-link>
    <s-router-link to="/com2">com2</s-router-link>
    <s-router-view></s-router-view>
  </div>
</template>

<script>

export default {
  
}
</script>

<style>

</style>

整個思路流程就是,註冊插件,監聽瀏覽器的hash改變事件,當hash改變的時候,修改某個vue實例的某個屬性,利用vue的響應式,使用到的地方也會改變,從而去更新router-view顯示的地方 html

須要準備的知識包括:

  • 如何註冊Vue插件
  • 如何註冊組件
  • Vue的mixin
  • render函數的用法

本例只實現了使用hash的方式的實現簡單的路由跳轉和顯示,其餘方法讀者有興趣的話能夠本身實現vue

github地址

相關文章
相關標籤/搜索