四十一、Vue-Router使用

郁子大约 6 分钟约 1833 字笔记Vue2尚硅谷张天禹VueRouter

(一)基本路由

1.安装 Vue-Router

  • 在 2022 年 02 月 07 日,Vue3 成为了默认版本
    • npm i vue 直接安装的是 Vue3
  • 同时 vue-router 也更新到了 v4
    • npm i vue-router 安装的是 VueRouter4
  • vue-router4 只能在 Vue3 中使用
  • Vue2 项目需要安装 vue-router3
npm i vue-router@3

2.应用插件

Vue.use(VueRouter);

3.编写 router 配置项

// 引入VueRouter
import VueRouter from "vue-router";
// 引入路由组件
import About from "../components/About";
import Home from "../components/Home";

// 创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
  routes: [
    {
      path: "/about",
      component: About,
    },
    {
      path: "/home",
      component: Home,
    },
  ],
});

// 暴露router
export default router;

4.实现切换

  • active-class 可配置高亮样式
<router-link active-class="active" to="/about">About</router-link>

5.指定展示位置

<router-view></router-view>

几个注意点

  • 路由组件通常存放在 pages 文件夹,一般组件通常存放在 components 文件夹
  • 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再挂载
  • 每个组件都有自己的 $route 属性,里面存储着自己的路由信息
  • 整个应用只有一个 router ,可以通过组件的 $router 属性获取到

(二)多级路由/嵌套路由

1.配置路由规则

  • 使用 children 配置项
routes: [
  {
    path: "/about",
    component: About,
  },
  {
    path: "/home",
    component: Home,
    children: [
      // 通过children配置子级路由
      {
        path: "news", // 子级路由路径一定不要写前缀/
        component: News,
      },
      {
        path: "messages",
        component: Messages,
      },
    ],
  },
];

2.跳转

  • 要写完整路径
<router-link to="/home/news">News</router-link>

(三)命名路由

1.作用

  • 可以简化路由的跳转

2.使用

1)给路由命名

{
  path: '/demo',
  component: Demo,
  children: [
    {
      path: 'test',
      component: Test,
      children: [
        {
          name: 'hello', // 给路由命名
          path: 'welcome',
          component: Hello
        }
      ]
    }
  ]
}

2)简化跳转

<!-- 简化前,需写完整的路径 -->
<router-link to="/demo/test/welcome">跳转</router-link>

<!-- 简化后,直接通过名字跳转 -->
<router-link :to="{name: 'hello'}">跳转</router-link>

<!-- 简化写法配合传递参数 -->
<router-link
  :to="{
    name: 'hello',
    query: {
      id: 666,
      title: '你好'
    }
  }"
>
  跳转
</router-link>

(四)路由的 query 参数

1.传递参数

<li v-for="m in messageList" :key="m.id">
  <!-- 跳转路由并携带query参数,to的字符串写法 -->
  <router-link :to="`/home/messages/detail?id=${m.id}&title=${m.title}`">{{ m.title }}</router-link>

  <!-- 跳转路由并携带query参数,to的对象写法 -->
  <router-link
    :to="{
      path: '/home/messages/detail',
      query: {
        id: m.id,
        title: m.title,
      },
    }"
  >
    {{ m.title }}
  </router-link>
</li>

2.接收参数

$route.query.id;
$route.query.title;

(五)路由的 params 参数

1.配置路由,声明接收 params 参数

{
  path: '/home',
  component: Home,
  children: [
    {
      path: 'news',
      component: News
    },
    {
      component: Messages,
      children: [
        {
          name: 'xiangqing',
          path: 'detail/:id/:title', // 使用占位符声明接收params参数
          component: Detail
        }
      ]
    }
  ]
}

2.传递参数

重要

路由携带 params 参数时,若使用 to 的对象写法,则不能使用 path 配置项

必须使用 name 配置项

<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link to="/home/messages/detail/666/你好">跳转</router-link>

<!-- 跳转并携带params参数,to的对象写法 -->
<router-link
  :to="{
    name: 'hello',
    params: {
      id: 666,
      title: '你好'
    }
  }"
>
  跳转
</router-link>

3.接收参数

$route.params.title;
$route.params.id;

(六)路由的 props 配置

  • 作用:让路由组件更方便地收到参数
{
  name: 'xiangqing',
  path: 'detail/:id/:title',
  component: Detail,

  // 第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
  props: {
    a: 900
  },

  // 第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
  props: true,

  // 第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
  props(route) {
    return {
      id: route.query.id,
      title: route.query.title
    }
  }
}

1.作用

  • 控制路由跳转时操作浏览器历史记录的模式

2.浏览器的历史记录有两种写入方式

  • 分别为 pushreplace
    • push 是追加历史记录
    • replace 是替换当前记录
  • 路由跳转的时候默认是 push

3.开启 replace 模式

<router-link replace ......>News</router-link>

(八)编程式路由导航

1.作用

  • 不借助 <router-link> 实现路由跳转,让路由跳转更加灵活

2.具体编码

// $router的两个API
this.$router.push({
  name: "xiangqing",
  params: {
    id: m.id,
    title: m.title,
  },
});

this.$router.replace({
  name: "xiangqing",
  params: {
    id: m.id,
    title: m.title,
  },
});

// 前进
this.$router.forward();

// 后退
this.$router.back();

/**
 * 可前进也可后退
 * 根据函数调用时传递的参数
 * 正数->前进,负数->后退
 */
this.$router.go(1);

(九)缓存路由组件

1.作用

  • 让不展示的路由组件保持挂载,不被销毁

2.具体编码

  • includes 接收的是 组件名 ,不是路由规则的 name
  • 不配置 includes 则所有展示在 keep-alive 标签中的组件都保持挂载
<!-- 缓存所有显示在keep-alive中的组件 -->
<keep-alive>
  <router-view></router-view>
</keep-alive>

<!-- 缓存一个路由组件 -->
<keep-alive include="News">
  <router-view></router-view>
</keep-alive>

<!-- 缓存多个路由组件 -->
<keep-alive :include="['News', 'Messages']">
  <router-view></router-view>
</keep-alive>

(十)两个新的生命周期钩子

1.作用

  • 路由组件所独有的两个钩子
  • 用于捕获路由组件的激活状态

2.具体名字

  • activated:路由组件被激活时触发
  • deactivated:路由组件失活时触发

(十一)路由守卫

1.理解

  • 御前侍卫:保护君王的安全
  • 路由守卫:保护路由的安全(权限)

2.作用

  • 对路由进行权限控制

3.分类

  • 全局守卫
  • 独享守卫
  • 组件内守卫

4.全局守卫

1)全局前置路由守卫

/**
 * 1.初始化的时候被调用
 * 2.每次路由切换之前被调用
 */
router.beforeEach((to, from, next) => {
  console.log("beforeEach", to, from);
  if (to.meta.isAuth) {
    // 判断当前路由是否需要进行权限控制
    if (localStorage.getItem("school") === "atguigu") {
      // 权限控制的具体规则
      next(); // 放行
    } else {
      alert("暂无权限查看!");
      // next({name: 'guanyu'});
    }
  } else {
    next(); // 放行
  }
});

2)全局后置路由守卫

/**
 * 1.初始化的时候被调用
 * 2.每次路由切换之后被调用
 */
router.afterEach((to, from) => {
  console.log("afterEach", to, from);
  if (to.meta.title)
    document.title = to.meta.title; // 修改网页的title
  else document.title = "vue_test";
});

5.独享守卫

beforeEnter: (to, from, next) => {
  console.log("beforeEnter", to, from);
  if (to.meta.isAuth) {
    if (localStorage.getItem("school") === "atguigu") {
      next();
    } else {
      alert("学校名不对,无权限查看!");
    }
  } else {
    next();
  }
};

6.组件内守卫

// 进入守卫,通过路由规则,进入该组件时被调用
beforeRouteEnter(to, from, next) {
  ......
},
// 离开守卫,通过路由规则,离开该组件时被调用
beforeRouteLeave(to, from, next) {
  ......
},

(十二)路由器的两种工作模式

1.哈希值

  • 对于一个 url localhost:8080/#/home/messages/detail
    • # 及其之后的内容表示 hash 值
  • hash 值不会包含在 HTTP 请求中
    • 即:hash 值不会带给服务器

2.分类

  • 分为 history 模式与 hash 模式
  • 默认使用的是 hash 模式

3.切换工作模式

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

// hash模式
const router = new VueRouter({
  mode: 'hash',
  routes: [{...}]
});

4.hash 模式

  • 地址中永远带着#号,不美观
  • 若以后将地址通过第三方手机 app 分享,若 app 校验严格,则地址会被标记为不合法
  • 兼容性较好

5.history 模式

  • 地址干净,美观
  • 兼容性和 hash 模式相比略差
  • 应用部署上线时需要后端人员支持,解决刷新页面服务端 404 的问题
上次编辑于: