vue 手写一个vue-router

实现效果如下:

vue 手写一个vue-router_第1张图片

1. 准备好环境

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

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

yarn add vue-router 安装vue-router创建一个router文件夹并使用:
vue 手写一个vue-router_第2张图片

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>

你可能感兴趣的:(vue,vue,vue-router)