Router路由

前端路由一共有三种模式:hash,history,memory ,常用2种为: hash模式 和 history模式

安装 vue-router

npm install vue-router@4

在vue项目里使用 router-link 替换a标签。

router-view

router-view 用来显示动态切换的组件内容。显示的是对应router-link 的路由组件。

// 1. 定义路由组件.
// 也可以从其他文件导入
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }

// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
]

// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = VueRouter.createRouter({
  // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。 createWebHashHistory / createWebHistory
  history: VueRouter.createWebHashHistory(),
  routes, // `routes: routes` 的缩写
})

// 5. 创建并挂载根实例
const app = Vue.createApp({})
//确保 _use_ 路由实例使
//整个应用支持路由。
app.use(router)

app.mount('#app')

// 现在,应用已经启动了!

指定路由模式

vue3 使用 history 属性替代了vue2的mode属性,可选值如下:

  • createWebHashHistory hash模式
  • createWebHistory history模式
  • creatMemoryHistory memory模式
const router = VueRouter.createRouter({
	history:createWebHashHistory
})

vue2路由指定模式

mode的可选值如下:hash,history,abstract(node环境强制开启模式)

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

带参数的动态路由

动态参数写法 /:参数名

{ path: '/users/:id', component: User },

获取动态参数

$route.params.id

路由可选参数 ?

{ path: '/users/:userId?' },

路由跳转 router.push

点击 router-link 时,内部会调用这个方法,所以点击 router-link :to="..." 相当于调用 router.push(...)

声明式编程式
<router-link :to="...">router.push(...)
// 字符串路径
router.push('/users/eduardo')

// 带有路径的对象
router.push({ path: '/users/eduardo' })

// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })

// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })

// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })

路由替换 router.replace

声明式编程式
<router-link :to="..." replace>router.replace(...)
router.push({ path: '/home', replace: true })
// 相当于
router.replace({ path: '/home' })

路由历史 router.go

// 向前移动一条记录,与 router.forward() 相同
router.go(1)

// 返回一条记录,与 router.back() 相同
router.go(-1)

// 前进 3 条记录
router.go(3)

// 如果没有那么多记录,静默失败
router.go(-100)
router.go(100)

路由命名

所有的路由命名都必须唯一。

路由配置:

const routes = [
  {
    path: '/user/:username',
    name: 'user',
    component: User,
  },
]

跳转路由配置方式一:

<router-link :to="{ name: 'user', params: { username: 'erina' }}">
  User
</router-link>

跳转路由配置方式二:

router.push({ name: 'user', params: { username: 'erina' } })

路由重定向 redirect

router通过redirect重定向路由。

const routes = [{ path: '/home', redirect: '/' }]
const routes = [{ path: '/home', redirect: { name: 'homepage' } }]

路由别名 alias

const routes = [{ path: '/', component: Homepage, alias: '/home' }]

路由守卫

全局前置守卫 beforeEach,通过next方法放行。
const router = createRouter({ ... })

router.beforeEach((to, from,next) => {
  // ...
  // 返回 false 以取消导航
  return false
})
全局解析守卫 beforeResolve
router.beforeResolve(async to => {
  if (to.meta.requiresCamera) {
    try {
      await askForCameraPermission()
    } catch (error) {
      if (error instanceof NotAllowedError) {
        // ... 处理错误,然后取消导航
        return false
      } else {
        // 意料之外的错误,取消导航并把错误传给全局处理器
        throw error
      }
    }
  }
})
全局后置守卫 afterEach
router.afterEach((to, from, failure) => {
  if (!failure) sendToAnalytics(to.fullPath)
})
独享路由守卫

直接在路由配置上定义 beforeEnter。

const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },
]

组件守卫

  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave
const UserDetails = {
  template: `...`,
  beforeRouteEnter(to, from) {
    // 在渲染该组件的对应路由被验证前调用
    // 不能获取组件实例 `this` !
    // 因为当守卫执行时,组件实例还没被创建!
  },
  beforeRouteUpdate(to, from) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
    // 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from) {
    // 在导航离开渲染该组件的对应路由时调用
    // 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
  },
}

路由懒加载

// 将
// import UserDetails from './views/UserDetails.vue'
// 替换成
const UserDetails = () => import('./views/UserDetails.vue')

const router = createRouter({
  // ...
  routes: [
    { path: '/users/:id', component: UserDetails }
    // 或在路由定义里直接使用它
    { path: '/users/:id', component: () => import('./views/UserDetails.vue') },
  ],
})

404配置

routes: [{
    path: '/:pathMatch(.*)*', // vue2
    path: '/:catchAll(.*)', // vue3
    name: 'NotFound',
    component: NotFound
}]

路由鉴权拦截

对于需要登录查看的路由,或者一定等级能查看的鉴权功能,需要用到路由全局前置守卫和路由元信息meta。

1.设置路由元信息:requiresAuth

{
    path: '/',
    name: 'home',
    component: HomeView,
    // 只有经过身份验证的用户才能创建帖子
    meta: { requiresAuth: true }
},

2.路由前置守卫

// 路由鉴权守卫
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth) {
    const flag = localStorage.getItem('loginSatus')
    // 登录标识假时就跳转到登录页面
    if (flag === 'true') {
      next()
    } else {
      next('/login')
    }
  } else {
    next()
  }
})