likes
comments
collection
share

全面拥抱Vue3,Vue-Router4 快速上手指南!

作者站长头像
站长
· 阅读数 66

大家好,我是 CoderBin

前言

Vue-Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。

声明:以下伪代码在 vue3 环境运行

1. 安装

npm i vue-router@4

2. 配置步骤

(1) src目录下,创建 router/index.js 文件,进行以下步骤:

  1. 按需导入路由对应的函数,和需要的跳转的组件
  2. 声明路由规则(也称路由映射表)
  3. 创建路由对象
  4. 向外共享路由对象
// 1. 
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from './components/Home.vue'

// 2. 
const routes = [
  { path: '/home', name: 'Home', component: Home}
]

// 3. 
const router = createRouter({
  history: createWebHashHistory(),  // 这里采用的是 hash 模式
  routes                            // 上面声明的路由规则
})

// 4. 
export default router

(2) main.js 文件中,导入并使用路由对象

import { createApp } from 'vue'
import App from './App.vue'
// 1. 导入路由对象
import router from './router/index.js'

// 2. 使用 use() 将路由对象安装为 vue 全局插件
createApp(App).use(router).mount('#app')

3. 声明路由出口 router-view

在 App 组件中的 template 模板中声明

<template>
    <router-view></router-view>
</template>

4. 设置路由链接 router-link

4.1 router-link 的属性

在组件中的 template 模板中设置链接,最简单的用法如下:

<router-link to="/home/users">用户管理</router-link>

注意:设置完路由链接别忘了还需要在 router/index.js 文件中编写对应的路由规则。

属性介绍

(1)to 属性:跳转的地址(常用)

<template>
  <rouer-link to="/home">首页</rouer-link>
</template>

(2) active-class 属性:链接被激活时触发的样式类

<template>
  <rouer-link to="/home" active-class="current">首页</rouer-link>
</template>

<style>
  /* 缺点:只能一个个添加该属性 */
  .current {
    color: red;
  }
</style>

(3) router 默认样式类

<style>
  /* 只要某一路由链接被触发,就会默认触发此类 */
.router-link-active {
  color: red
}
</style>

(4) linkActiveClass :是创建路由对象时的一个可选项

const router = createRouter({
  ···
  linkActiveClass = 'current'
  // 此类优先级最高,在组件中有路由链接被触发,有此类的样式就会执行,
})

(5) replace 属性:替换地址,不存在历史记录

<template>
  <router-link to='/home' replace>首页</router-link>
</template>

(6) exact-active-class属性: 链接精准激活时,应用于渲染的 router-link 的 class,默认是router-link-exact-active;

4.2 router-link 的 slot(用得少,简单看看就好)

  1. 在vue-router3.x的时候,router-link有一个tag属性,可以决定router-link到底渲染成什么元素:
  • 但是在vue-router4.x开始,该属性被移除了;
  • 而给我们提供了更加具有灵活性的v-slot的方式来定制渲染的内容;
  1. v-slot如何使用呢?
  • 首先,我们需要使用custom表示我们整个元素要自定义,如果不写,那么自定义的内容会被包裹在一个 a 元素中;
  • 其次,我们使用v-slot来作用域插槽来获取内部传给我们的值:
  1. prop 的值:
  • href:解析后的 URL;
  • route:解析后的规范化的route对象;
  • navigate:触发导航的函数;
  • isActive:是否匹配的状态;
  • isExactActive:是否是精准匹配的状态;
<template>
<!-- <router-link> 的插槽,里面是什么就渲染什么-->
    <!-- props: href 跳转的链接 -->
    <!-- props: route对象 -->
    <!-- props: navigate导航函数 前往路由所在的位置-->
    <!-- props: isActive 是否当前处于活跃的状态 -->
    <!-- props: isExactActive 是否当前处于精确的活跃状态 -->
    <!-- custom 属性,表示整个元素要自定义 -->
    <router-link to="/home" v-slot="props" custom>
      <button @click="props.navigate">{{props.href}}</button>
      <button @click="props.navigate">哈哈哈</button>
      <span :class="{'active': props.isActive}">{{props.isActive}}</span>
      <span :class="{'active': props.isActive}">{{props.isExactActive}}</span>
      <!-- <p>{{props.route}}</p> -->
    </router-link>
</template>

5. 编程式导航

import { useRouter } from 'vue-router'

// 创建 router 对象,调出方法
const router = useRouter()
const click = () => {
  // 1. 普通写法
  // router.push('/home')
  // router.replace('/about')

  // 2. 对象的写法,可以添加 query 参数,跳转到对应页面后,可以通过 route.query 获取到 query 参数
  router.push({
    path: '/home',
    query: {
      name: 'CoderBin',
      age: 18
    }
  })
}

6. router 与 route 的区别

router:是 vue-router 的一个 对象,这个对象是 全局的对象,包含了所有的路由,和许多关键的 属性和对象

route:是一个跳转的路由对象,每个路由都会有一个 route 对象,是一个 局部的对象,可获取当前组件对应的 name、path、query、params等...

7. 动态路由

router/index.js 中,路径里面的 id 就为 动态参数

routes = [
  { path: '/new/:id', component: New}
]

App.vue 中,这个 id 值可以通过请求数据,动态获取 id,以实现 动态路由

<template>
  <router-link to='/new/001'>新闻</router-link>
</template>

7.1 获取动态路由参数

第一种方式:New.vue 中,注意:其中的 id 为路由规则中定义的路由参数名

<template>
  <p>{{ $route.params.id }}</p>
</template>

第二种方式:New.vue

<script setup>
  import { useRoute } from 'vue-router'
  
  const route = useRoute()
  console.log(route.params.id)
</script>

8. 设置 NotFound 页面

对于那些没有匹配到的路由,我们通常会匹配到固定的某个页面

比如 NotFound 的错误页面中,这个时候我们可编写一个动态路由用于匹配所有的页面;

const route = [
    {
    // 对于那些没有匹配到的路由,我们通常会匹配到固定的某个页面
    // 注意:
    // 1. "/:pathMatch(.*)" 会匹配到不存在的路由地址
    // 2. 我们可以通过 $route.params.pathMatch 获取到传入的参数:
    // 3. 还有一种写法:"/:pathMatch(.*)*",就是后面多了个*号,区别在于获取参数时会以 / 号为分隔符,组成一个数组
    path: "/:pathMatch(.*)",
    component: () => import("../pages/NotFound.vue")
  }
]

8. 路由懒加载

  1. 把不同路由对应的组件分成不同代码块,当路由被访问时才加载对应组件
  2. 性能优化,更加高效;
// 1. 可以这样导入
const Home = () => import('./components/Home.vue')

// 3. 把组件按组分块,这样打包时候会被打包到一个地方
const New = () => import(/*webpackChunckName:"group-new"*/'./components/New.vue')

const route = [
  { path: '/home', component: Home},
  // 2. 也可以直接写在路由规则中,这种称为 动态导入
  { path: '/about', component: ()=>import('./components/About.vue')}
]

9. 嵌套路由 children

router/index.js中,使用 children 选项实现,注意:子路由里面不需要加 "/" 号

// 路由规则
const routes = [
  path: 'mine',
  component: Mine,
  children: [
    { path: 'msg', component: Msg}
  ]
]

10. 路由重定向 redirect

// 路由规则
const routes = [
  // 当访问根路径时,自动跳转至 /home
  { path: '/', redirect: 'home'},
  { path: '/home', component: Home}
]

11. 参数传递

在组件中,使用 query 属性,以对象形式传递参数

<template>
  <router-link :to="{path: '/about'}", query:{name: 'jack', age: 22}></router-link>
</template>

注意:抽离成方法也行

12. 全局前置守卫 & 路由元信息

  1. 全局前置守卫:当一个导航触发,在跳转之前会被这个前置守卫拦截下来,并执行守卫里面的相关操作

  2. meta 路由元信息:如果希望将任意信息附加到路由上,如过渡名称,谁可以访问等,就可以通过接收属性对象的 meta 属性来实现,并且他在路由地址导航守卫 上都可以被访问到

注意:router/index.js 中,mate 要作为选项被写到路由规则中,值可以是任意类型,一般用对象形式。

  • 在对应组件中可以通过route.meta获取meta值
import { useRoute } from "vue-router"
const route = useRoute()
console.log('home 的路由元信息:',route.meta);
  • 在前置导航守卫中可以通过to.meta获取meta值;
const routes = [
  { path: '/home', component: Home, meta: {title: '首页'}}
]

// 声明全局前置守卫
/**
 * 返回值问题:
 *    1.false: 不进行导航
 *    2.undefined或者不写返回值: 进行默认导航
 *    3.字符串: 路径, 跳转到对应的路径中
 *    4.对象: 类似于 router.push({path: "/login", query: ....})
 */
router.beforeEach((to, from) => {
  // to: Route对象, 即将跳转到的Route对象
  // from: Route对象, 
  // next: 第三个参数可选,vue-router4.x 已经不推荐使用,推荐使用return控制跳转
  console.log('导航守卫里面获取路由元信息:',to.meta);
  if (to.path !== "/login") {
    const token = window.localStorage.getItem("token");
    if (!token) {
      return "/login"
    }
  }
  // return false;    //不进行导航 
})

13. 全局后置钩子(守卫)

后置钩子:当跳转到了当面界面,做一些操作

router/index.js

router.after((to,from)=>{
  document.title = to.meta.title
})

14. 路由独享的守卫(了解)

直接在路由规则上定义 beforeEnter 守卫

const route = [
  { path: '/home', component: Home,
    beforeEnter: (to, from ) => { /* 一些操作 */ }
  }
]

注:只在进入当前路由时触发,可传递数组进去 beforeEnter : [fn1, fn2]

15. 组件内的守卫(了解)

在组件内自由定义导航守卫,极少用到

OnBeforeRouteUpdate((to, from, next) => { .... })
OnBeforeRouteLeave((to, from, next) => { .... })

16. keep-aclive 组件缓存

将当前导航到的组件缓存下来,下次使用时,直接取出,避免了组件重复创建与销毁(数据不断请求) App.vue 中,直接添加以下代码即可

<router-view v-slot="{ Component }">
    <keep-alive>
      <component :is="Component" />
    </keep-alive>
</router-view>

(1) exclude 属性,任何名称匹配的组件都不会被缓存

<router-view v-slot="{ Component }">
    <keep-alive exclude="About"
      <component :is="Component" />
    </keep-alive>
</router-view>

也可以多个:

<keep-alive :exclude="['About', 'New']"> ... </keep-alive>

(2) include 属性,任何名称匹配的组件都会被缓存

<keep-alive include="Home"> ... </keep-alive>

17. router-view 的 slot,配合 transition 实现切换组件时候的动画

router-view也提供给我们一个插槽,可以用于 transition 和 keep-alive 组件来包裹你的路由组件:

  • Component:要渲染的组件;
  • route:解析出的标准化路由对象;
<template>
  <!-- 注意:这里直接将 transition 和 keep-alive 一起用了 -->
  <router-view v-slot="props">
    <transition>
      <keep-alive>
        <component :is="props.Component"></component>
      </keep-alive>
    </transition>
  </router-view>
</template>

<style scope>
  .v-enter-from,
  .v-leave-to {
    opacity: 0;
  }

  .v-enter-active,
  .v-leave-active {
    transition: opacity 1s ease;
  }
</style>

18. 动态添加路由

说明:某些情况下我们可能需要动态的来添加路由:

  • 比如根据用户不同的权限,注册不同的路由;
  • 这个时候我们可以使用一个方法 addRoute;
//TODO 动态添加路由
// 例如:用户的身份为管理员的时候,才注册某些带权限的路由,这个一般在前置导航守卫里面做判断
const categoryRoute = {
  path: "/category",
  component: () => import("../pages/Category.vue")
}
// 添加顶级路由对象,也就是最外层的路由
router.addRoute(categoryRoute);

// 添加二级路由对象,某一路由的子路由
router.addRoute("home", {
  path: "moment",
  component: () => import("../pages/HomeMoment.vue")
})

19. 动态删除路由

删除路由有以下三种方式:

  1. 添加一个已经存在的,name 属性值相同的路由,替换旧的路由
router.addRoute({path: '/about', name: 'order', component: './About.vue'})
  1. 通过 removeRoute() 方法,传入路由的名称,删除路由,一般用这一种方式
router.addRoute({path: '/about', name: 'about', component: './About.vue'})
// 删除路由
router.removeRoute('about')
  1. 通过 addRoute() 方法的返回值回调
const removeRoute = router.addRoute(routeRecord)
removeRoute() //删除路由如果存在的话

20. 路由的其他方法补充

  1. router.hasRoute(): 检查路由是否存在
  2. router.getRoute(): 获取一个包含所有路由记录的数组

每文一句:科学研究好象钻木板,有人喜欢钻薄的;而我喜欢钻厚的。

ok,关于 Vue-Router4 的简单使用就到这里,看到这里相信你对 Vue-Router4 已经有了简单的了解。如果想对 Vue-Router4 进行更加深入的理解,请移步 Vue-Router4中文文档 深入研究。如果本章内容对你有所帮助的话可以点赞+收藏,有任何疑问都可以在评论区留言,大家一起探讨,谢谢!

转载自:https://juejin.cn/post/7129831320988942367
评论
请登录