每天学习一个vue插件(22)——vue-router

818 阅读3分钟

只要有你想要保护的东西,那就拔剑好了

前言

1 router

构造器

VueRouter

import VueRouter from 'vue-router'

// VueRouter 高版本问题
// Error: Redirected when going from “/login” to “/home” 
// via a navigation guard
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, onResolve, onReject) {
  if (onResolve || onReject) {
    return originalPush.call(this, location, onResolve, onReject)
  }

  return originalPush.call(this, location).catch(err => err)
}

const router = new VueRouter({ routes })

属性

options

// 路由信息
// 可筛选出特定路由route,用于跳转拦截
router.options = {
  routes: [route]
}

方法

beforeEach

// 路由跳转前触发,此时仍处于当前页面
// 可用于登录拦截
// 可用于跳过测试页面,直接跳转结果页面
router.beforeEach((to, from, next) => {
  // 如果没有登录,跳转登录页
  if (!token) {
    next('/login')
  }
  
  // 如果做过测试,跳转结果页
  const reportRoute = router.options.routes.find(
    route => route.name === 'Report'
  )
  if (to.name === 'Test' && reportRoute.meta.hasReport) {
    next('/report')
  }
  
  // next 必须执行,否则无法跳转
  // 参数为String, 传path
  // 参数为对象,{path, name?, params?, query?}
  // 参数为false,阻止跳转
  next()
})

2 routes

同步路由

import Home from '@views/Home.vue'
import About from '@views/About.vue'
import NotFount from '@views/NotFount.vue'
const routes = [
  {
    path: '/',
    redirect: '/home'  // 默认进入 Home 页面
  },
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/about', // 匹配 about 进入 About 页面
    name: 'About',
    component: About
  },
  {
    path: '*', // 没有匹配以上路由,则进入 NotFount 页面
    name: 'NotFount',
    component: NotFount
  }
}

异步路由

const routes = [
  ...
  {
    path: '/home',
    name: 'Home',
    component: () => import('@views/Home.vue')
  },
  {
    path: '/about', // 匹配 about 进入 About 页面
    name: 'About',
    component: () =>
      // 打包成单独的chunk
      // chunk名称为 about
      import(/* webpackChunkName: "about" */ '@views/About.vue'),
  },
  ...
}

动态路由

const routes = [
  ...
  {
    path: '/product/:id', // param传参
    name: 'Product',
    component: () => import('@views/Product.vue'),
    // 解耦props
    // 不使用 this.$route.params.id 取参数
    // 直接使用 props:['id'] 接收后,再使用this.id 取参
    props: route => ({...route.params}) 
  }
  ...
}

// 路由跳转
this.router.push({
  path: 'product/123'
})

this.router.push({
  name: 'Product'
  params: {
    id: 123
  }
})

子路由

const routes = [
  ...
  {
    path: '/about',
    name: 'About',
    component: () =>
      import(/* webpackChunkName: "about" */ '@views/About.vue'),
    children: [
      {
        path: '', // 默认进入 profile 子页面
        redirect: 'profile'  
      },
      {
        // 相对路径
        // 使用 path: '/about/profile' 跳转
        path: 'profile', 
        name: 'Profile',
        component: () =>
          import(/* webpackChunkName: "about" */ '.@views/Profile.vue')
      },
      {
        // 绝对路径
        // 直接使用 path: '/posts' 跳转
        path: '/posts', 
        name: 'Posts',
        component: () =>
          import(/* webpackChunkName: "about" */ '@views/Posts.vue')
      }
    ]
  }
  ...
]

3.route

常规属性

{
  // 跳转路由
  path: '/home',
  // 路由名称
  name: 'Home',
  // 路径映射的组件
  component: Home
}

重定向

{
  ...
  // 默认进入
  path: '/',
  // 重定向到 Home 页面
  redirect: '/home'
  ...
}

路由解耦

{
  ...
  // 解耦props
  // 不使用 this.$route.params.id 取参数
  // 直接使用 props:['id'] 接收后,再使用this.id 取参
  props: route => ({...route.params}) 
  ...
}

路由元

{
  ...
  // 路由信息
  // 存储该路由特定变量
  meta:{
    keepAlive: true,
    auth: true,
    breadcrums: ['首页', '关于', '个人'],
    hasToReport: false
  }
  ...
}

路由拦截

{
  path: '/report',
  name: 'Report',
  component: () =>
      import(/* webpackChunkName: "about" */ '../views/Report.vue'),
  meta: {
    hasToReport: false
  },
  beforeEnter: (to, from, next) => {
    to.meta.hasToReport = true
    next()
  }
}

4.注意

1.高版本路由,没有catch错误,需做单独处理
2.解耦props后,动态路由须使用 params 传参
3.权限等涉及路由跳转拦截问题,在beforeEach里处理
4.redirect可使用函数

尾声

人挺多了,抓紧我,我可不想把你给弄丢了~

晚安 ^_^

参考链接

往期回顾