实现一个简单的 vue-router

功能介绍:
1、只为1级路由之间跳转,适合看源码之前看看逻辑
2、此模式为 hash 模式;history 模式跟这个大差不差

直接看代码,提示全在代码里

/**
 * 最简陋router:只支持一级路由,适合看 vue-router 源码之前看看
 * 此模式为 hash 模式,history 模式 大差不差
 */
let _Vue =  null
export default class VueRouter {
  // 因为vue挂载是使用Vue.use():如果是函数,则直接调用;如果是对象则会去找这个对象里面的install方法;第一个参数是Vue实例;
  static install(Vue) {
    // 判断插件是否安装
    if (VueRouter.install.installed) return
    // 如果未安装则设置为已安装-防止多次挂载
    VueRouter.install.installed = true
    // 把vue构造函数记录到全局变量
    _Vue = Vue
    // 把创建Vue实例时候传入的router对象注入到Vue实例上
    _Vue.mixin({
      beforeCreate() {
        if (this.$options.router){
          _Vue.prototype.$router = this.$options.router
          this.$options.router.init()
        }
      }
    })
  }
  constructor(options) {
    // 传递过来的配置项
    this.options = options;
    // 路由地图
    this.routerMap = {};
    // 动态路由数据
    this.data = _Vue.observable({
      current: location.hash
    })
  }
  // 初始化
  init() {
    this.createRouteMap()
    this.initComponents(_Vue)
    this.initEvent()
  }
  // 初始化事件
  initEvent() {
    // 当浏览器触发前进和后退的时候触发函数
    onhashchange = () => {
      this.data.current = window.location.hash
    }
  }
  // 创建路由地图
  createRouteMap(arr = this.options, index = 'routes', path = '') {
    // 遍历所有的路由规则,把路由规则解析成键值对的形式,存储到routerMap中
    arr[index].forEach(route => {
      // 处理子集不写 / 和 写/ 的情况 
      let pathEnd = `${path}${route.path.indexOf('/') === 0?'':'/'}${route.path}`
      this.routerMap[pathEnd] = route.component
      // 如果发现有子集,则递归调用
      if (Array.isArray(route.children)) {
        this.createRouteMap(route, 'children', pathEnd)
      }
    });
  }
  // 初始化组件
  initComponents(Vue) {
    let _this = this
    Vue.component('router-link', {
      props: {
        to: String
      },
      /**
       * 开启template这行需要在vue.config.js 配置 runtimeCompiler: true。意为 运行时编译模板。官网有介绍 。开启后请重新启动项目。
       * 官网地址 https://cli.vuejs.org/zh/config/#runtimecompiler
       */
      // template: '<a :href="to"><slot></slot></a>'
      render (h) {
        return h('a', {
          attrs: {
            href: '#' + this.to
          },
          on: {
            click: this.clickHandle
          }
          // 插槽
        }, [this.$slots.default])
      },
      methods: {
        clickHandle() {
          // 设置当前hash给动态路由-联动更新页面
          this.$router.data.current = window.location.hash
        }
      },
    })
    Vue.component('router-view', {
      render(h) {
        // 这里this指向当前vue,而不是咱们的vue router
        return h(_this.routerMap[_this.data.current.replace('#', '')||'/'])
      }
    })
  }
}

引用
直接vue cli 创建一个项目 修改引入路径即可(注:history模式得删除掉,此只支持hash模式)

import Vue from "vue";
import Home from "../views/Home.vue";
import VueRouters from '../vue-router'

Vue.use(VueRouters)

const routes = [
  {
    path: "/",
    name: "Home",
    component: Home,
  },
  {
    path: "/about",
    name: "About",
    component: () =>
      import(/* webpackChunkName: "about" */ "../views/About.vue")
  },
];

const router = new VueRouters({
  routes
})

export default router;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值