vue 手写一个vue-router

实现效果如下:

1. 准备好环境

使用 vue/cil 初始化项目配置:

npm install -g @vue/cli    //全局安装@vue/cli
vue create demo-vue        //创建项目

yarn add vue-router 安装vue-router创建一个router文件夹并使用:

2. 实现目的

router/index.js内容如下:(我们的目的将引入自写的vue-router实现vue路由跳转功能)

import vue from 'vue'
//import vueRouter from 'vue-router'       //使用官方 vue-router 插件
import vueRouter from './my-vue-router'    //使用我们直接实现的 vue-router 插件

vue.use(vueRouter)                         //此时执行 my-vue-router 内 install 方法

const routes = [
  {
    path: '/',
    redrect: '/a'
  },
  {
    path: '/a',
    name: 'a',
    component: () => import('../views/a.vue')
  },
  {
    path: '/b',
    name: 'b',
    component: () => import('../views/b.vue')
  }
]

const router = new vueRouter({
  mode: 'hash',        //哈希路由
  routes
})

export default router  //main.js 引入实例化的 router 添加至 this.$options.router 中

3. 实现原理

router/my-vue-router.js 实现过程如下:

let Vue //声明一个变量用来存储install内接收的vue实例 给 constructor 内调用

class vueRouter {
  constructor(options) {
    this.$options = options    //用于通过全局 this.$options.router.$options 获取

    const initail = window.location.hash.slice(1) || '/'
    Vue.util.defineReactive(this, 'current', initail)    //监听数据响应式渲染页面
    window.addEventListener('hashchange', () => {        //监听哈希路由变化
      this.current = window.location.hash.slice(1)       //改变触发 render 渲染页面
    })
  }

  push() {
    console.log("跳转页面");
  }
}

vueRouter.install = function(_vue) {
  Vue = _vue

  Vue.mixin({
    beforeCreate() {
      if (this.$options.router) {
        Vue.prototype.$router = this.$options.router  	//将全局数据注入组件
      }
    }
  })

  Vue.component('router-link', {                        //注册全局 router-link 组件
    props: {
      to: {
        type: String,
        required: true
      }
    },
    render(h) {
      return h(
        'a',
        {
          attrs: { href: '#' + this.to }
        },
        this.$slots.default
      )
    }
  })

  Vue.component('router-view', {                        //注册全局 router-view 组件
    render(h) {
      console.log(" this.$router",  this.$router);
      const route = this.$router.$options.routes.find((route) => {
        return route.path == this.$router.current
      })

      return h(route.component)                        //将组件渲染返回
    }
  })
}

export default vueRouter

3. 使用手写vue-router:

a.vueb.vue 可任意写

<template>
  <div id="app">
    <router-link to="/a">aaa</router-link> |
    <router-link to="/b">bbb</router-link>
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'App'
}
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值