最近也在察看vue3新个性,抽空玩一玩嵌套路由的vue-router,间接上代码

我的项目目录构造

代码展现

  • app.vue
<template>  <div id="app">    <div>      <router-link to="/">Index</router-link> |      <router-link to="/person">Person</router-link> |      <router-link to="/person/info">PersonInfo</router-link>    </div>    <!-- 一级路由 -->    <router-view />  </div></template><style>#app{  display: flex;  flex-direction: column;  align-items: center;}</style>
  • Index.vue
<template>  <div class="index">    <h1>this is index page</h1>  </div></template>
  • Person.vue
<template>  <div class="person">    <h1>this is person page</h1>     <!-- 二级路由 -->    <router-view />  </div></template>
  • PersonInfo.vue
<template>  <div class="personInfo">    <h2>this is personInfo page</h2>  </div></template>

vue全家桶视频解说:进入学习

js文件

  • main.js
import Vue from 'vue'import App from './App.vue'import router from './router'new Vue({  router,  render: h => h(App)}).$mount('#app')
  • babel.config.js
  • 须要增加babel依赖反对新语法,如可选链
  • npm install --save-dev @babel/core @babel/cli
  • npm install --save-dev @babel/plugin-proposal-optional-chaining
module.exports = {  presets: [    '@babel/preset-env'  ],  plugins: ['@babel/plugin-proposal-optional-chaining']}
  • router目录下文件
  • index.js
import Vue from "vue";import VueRouter from "./vue-router";import Index from "../views/Index.vue";import Person from "../views/Person.vue";import PersonInfo from "../views/PersonInfo.vue";Vue.use(VueRouter);const routes = [  {    path: "/",    name: "Index",    component: Index  },  {    path: "/person",    name: "Person",    component: Person,    children:[      {        path: "/person/info",        name: "PersonInfo",        component: PersonInfo      }    ]  }];const router = new VueRouter({  routes});export default router;
  • vue-router.js
    这里先借助Vue的工具Vue.util.defineReactive实现数据响应式,后续再手撕这个库
import routerLink from "./router-link";import routerView from "./router-view";let Vue;class VueRouter {  constructor(options) {    this.$options = options    this.current = window.location.hash.slice(1) || "/"    // 设置响应式数组数据    Vue.util.defineReactive(this, "routerArray", [])    // 监听hash值变动    window.addEventListener("hashchange", this.hashChange.bind(this))    this.getRouterArray()  }  hashChange() {    this.current = window.location.hash.slice(1) || "/"    this.routerArray = []    this.getRouterArray()  }  getRouterArray(routes) {    routes = routes || this.$options.routes    for (const route of routes) {      if (this.current === '/' && route.path === '/') {        this.routerArray.push(route)        return      }      if (this.current.indexOf(route.path) !== -1 && route.path !== '/') {        this.routerArray.push(route)        if (route.children) {          // 递归子路由          this.getRouterArray(route.children)        }        return      }    }  }}VueRouter.install = function(_Vue) {  Vue = _Vue  // Vue全局混入,等new Vue中的router实例创立之后挂载到Vue上  Vue.mixin({    beforeCreate() {      if (this.$options.router) {        Vue.prototype.$router = this.$options.router      }    },  });  // 注册router-link和router-view全局组件  Vue.component("router-link", routerLink)  Vue.component("router-view", routerView)}export default VueRouter
  • router-link.js
export default {  props: {    to: {      type: String,      required: true    }  },  render(h) {    return h(      "a",      {        attrs: {          href: "#" + this.to,        },      },      this.$slots.default    );  }};
  • router-view.js
export default {  render(h) {    // 设置嵌套路由标识    this.$vnode.data.rv = true    // 嵌套路由设置深度    let depth = 0    let parent = this.$parent    while (parent) {      // 下级还有嵌套路由标识rv为true的,深度加一      if (parent.$vnode?.data?.rv) {        depth++      }      parent = parent.$parent    }    // 简略解决    const route = this.$router.routerArray[depth]    return h(route?.component);  }};
  • 效果图

好了,明天就玩到这里了,下次再玩别的哈