vue-router源碼實現

1. 目錄結構

在這裏插入圖片描述

2.實現vue-router源碼

// kvue-router.js
/* eslint-disable */ // 禁止eslint
let Vue;
class VueRouter {
  constructor(options){ // router傳入參數
    this.$options = options;
    this.routeMap = {}; // 所有的routes組件實例
    this.app = new Vue({ // 獲取當前的vue
      data: {
        current: '/'
      }
    })
  }

  // vue-router初始化 任務
  init() {
    this.bindEvents();
    this.createRouteMap(this.$options);
    this.initComponent()
  }

  // 全局添加默認綁定任務
  bindEvents() {
    window.addEventListener('load',this.onHashChange.bind(this),false);
    window.addEventListener('hashchange',this.onHashChange.bind(this),false);
  }

  // 獲取hash地址
  onHashChange() {
    this.app.current = window.location.hash.slice(1) || '/';
  }

  // 獲取路由配置裏面的地址
  createRouteMap(options) {
    options.routes.forEach(item => {
        this.routeMap[item.path] = item;
    })
}
  // 初始化默認router標籤
  initComponent() {
    // 聲明兩個全局組件
    Vue.component('router-link', {
      props: {
          to: String
      },
      render(h) {
          // 目標是:<a :href="to">xxx</a>
          return h('a', {attrs:{href: '#'+this.to}}, this.$slots.default)
          // return <a href={this.to}>{this.$slots.default}</a>
      }
    });

    // hash -> current -> render
    Vue.component('router-view', {
        // 箭頭函數能保留this指向,這裏指向VueRouter實例
        render: (h) => {
            const Comp = this.routeMap[this.app.current].component;
            return h(Comp);
        }
    })
  }
}

// 插件邏輯
VueRouter.install = function(_vue){
  Vue = _vue;
  Vue.mixin({
    beforeCreate() {
      if(this.$options.router){
        // Vue.prototype.$router = this.$options.router; // 原型鏈上添加router屬性
        this.$options.router.init() // 調用vue插件中的init方法
      }
    },
  })
}
export default VueRouter

3.路由配置頁面引入kvue-router.js

// router.js
import Vue from 'vue' // 引入vue
import Router from './kvue-router' // 引入kvue-router

// 使用自定義router插件
Vue.use(Router)

// 實例化vue對象
const router = new Router({
  mode: 'hash',
  routes: [
    {
      path:'/home',
      title: 'home',
      component: () => import('./components/base/home.vue')
    },
    {
      path:'/list',
      title: 'list',
      component: () => import('./components/base/list.vue')
    },
  ]
})

export default router

4.main.js頁面引入router文件,並且掛載到Vue上

// main.js 

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = true

new Vue({
  render: h => h(App),
  router
}).$mount('#app')

5.app.vue文件顯示router標籤

// app.vue
<template>
  <div id="app">
    <router-link to="/home">這是跳到home</router-link><br>
    <router-link to="/list">這是跳到list</router-link>
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'App',
  data() {
    return {
      name: ''
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

6.頁面顯示

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章