Vue-Router 官网速通(上)

简介: Vue-Router 官网速通(上)

一:介绍

1. 什么是 Vue Router

是 Vue.js 的官方路由。功能包括:1. 路由映射。2. 动态路由。3. 路由配置。4. 路由参数。5. 过渡效果。6. 导航控制。7. CSS 类链接。8. HTML5 模式。9. 滚动行为。10. URL 编码

2. 安装

对于一个现有使用 JS 包管理的项目,添加 Vue Router 依赖:

npm install vue-router@4
# or
yarn add vue-router@4
# or
pnpm add vue-router@4

通过 create-vue 脚手架创建一个基于 Vite 的新项目,加入 Vue Router 的选项:

npm create vue@latest
# or
yarn create vue
# or
pnpm create vue

二:基础

1. 入门

router-view 显示与 URL 对应的组件。可以放在任何地方,以适应布局。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script src="https://unpkg.com/vue@3"></script>
    <script src="https://unpkg.com/vue-router@4"></script>
 
    <div id="app">
      <h1>Hello App!</h1>
      <p>
        <!--使用 router-link 组件进行导航 -->
        <!--通过传递 `to` 来指定链接 -->
        <!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
        <router-link to="/">Go to Home</router-link>
        <router-link to="/about">Go to About</router-link>
      </p>
      <!-- 路由出口 -->
      <!-- 路由匹配到的组件将渲染在这里 -->
      <router-view></router-view>
    </div>
  </body>
  <script>
    // 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 模式。
      history: VueRouter.createWebHashHistory(),
      routes, // `routes: routes` 的缩写
    });
 
    // 5. 创建并挂载根实例
    const app = Vue.createApp({});
    //确保 _use_ 路由实例使
    //整个应用支持路由。
    app.use(router);
 
    app.mount("#app");
  </script>
</html>

在 Vue3 中通过调用 useRouter 和 useRoute 函数创建实例来访问。

<script setup lang="ts">
  import { useRouter, useRoute } from "vue-router";
 
  const router = useRouter();
  const route = useRoute();
 
  router.push("/"); // 跳转
  route.params; // 参数
</script>

2. 动态路由匹配

多个匹配路由映射到同一组件,通过一个动态字段来实现,称之为路径参数,路径参数用冒号 : 表示。如下 /users/johnny 和 /users/jolyne 会映射到同一个路由。

const User = {
  template: "<div>User</div>",
};
 
// 这些都会传递给 `createRouter`
const routes = [
  // 动态字段以冒号开始
  { path: "/users/:id", component: User },
];

通过 this.$route.params 来访问 URL 上的参数:

const User = {
  template: "<div>User {{ $route.params.id }}</div>",
};

路由可以设置多个参数,在 $route.params 上相对应:

const User = {
  template: "<div>User</div>",
};
 
// 传递给 `createRouter`
const routes = [
  // 动态字段以冒号开始
  { path: "/users/:username/posts/:postId", component: User },
];
 
// 匹配路由:/users/eduardo/posts/123
// $route.params:{ username: 'eduardo', postId: '123' }

2.1 响应路由参数的变化

同一路由的不同参数跳转,因为映射的是相同组件,所以复用组件显得更高效,但生命周期函数就不会被调用,比如从 /users/johnny 导航到 /users/jolyne。要对同一路由的参数做出响应,需要用 watch 监听:

// vue3
import { watchEffect } from "vue";
watchEffect(() => {
  console.log(1, route.params, route.query);
});

2.2 捕获所有路由或 404 Not found 路由

想匹配任意路径,使用路径参数正则表达式,在路径参数后面的括号中加入正则表达式 :

const routes = [
  // 将匹配所有内容并将其放在 `$route.params.pathMatch` 下
  { path: "/:pathMatch(.*)*", name: "NotFound", component: NotFound },
  // 将匹配以 `/user-` 开头的所有内容,并将其放在 `$route.params.afterUser` 下
  { path: "/user-:afterUser(.*)", component: UserGeneric },
];

3. 路由的匹配语法

大多数应用都会使用 /about 静态路由和 /users/:userId 动态路由,但是 Vue Router 提供了更多的方式!

3.1 在参数中自定义正则

两个路由 /:orderId 和 /:productName,会匹配完全相同的 URL,需要一种方法来区分他们,最简单的方法是添加一个静态部分来区分:

const routes = [
  // 匹配 /o/3549
  { path: "/o/:orderId" },
  // 匹配 /p/books
  { path: "/p/:productName" },
];

如果不想添加静态部分,也可以添加正则,orderId 总是一个数字,productName 可以是任何东西。以在括号中为参数指定正则,现在,/25 将匹配 /:orderId,其他情况匹配 /:productName。

const routes = [
  // /:orderId -> 仅匹配数字
  { path: "/:orderId(\\d+)" },
  // /:productName -> 匹配其他任何内容
  { path: "/:productName" },
];

TIP:确保转义反斜杠( \ ),就像对 \d (变成\\d)所做的那样,在 JS 中实际传递字符串中的反斜杠字符。

3.2 可重复的参数

匹配 /first/second/third 路由,应该用 \*(0 个或多个)和 +(1 个或多个)将参数标记为可重复:

const routes = [
  // /:chapters ->  匹配 /one, /one/two, /one/two/three, 等
  { path: "/:chapters+" },
  // /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等
  { path: "/:chapters*" },
];

提供了参数数组,而不是字符串,并且在使用命名路由时也需要你传递一个数组:

// 给定 { path: '/:chapters*', name: 'chapters' },
router.resolve({ name: "chapters", params: { chapters: [] } }).href;
// 产生 /
router.resolve({ name: "chapters", params: { chapters: ["a", "b"] } }).href;
// 产生 /a/b
 
// 给定 { path: '/:chapters+', name: 'chapters' },
router.resolve({ name: "chapters", params: { chapters: [] } }).href;
// 抛出错误,因为 `chapters` 为空

可以与正则结合使用:

const routes = [
  // 仅匹配数字
  // 匹配 /1, /1/2, 等
  { path: "/:chapters(\\d+)+" },
  // 匹配 /, /1, /1/2, 等
  { path: "/:chapters(\\d+)*" },
];

3.3 Sensitive 与 strict 路由配置

默认情况下,所有路由是不区分大小写和带尾部斜线的路由的。例如,路由 /users 将匹配 /users、/users/、/Users/。通过 strict 和 sensitive 选项来修改。

const router = createRouter({
  history: createWebHistory(),
  routes: [
    // 将匹配 /users/posva 而非:
    // - /users/posva/ 当 strict: true,尾部不能有斜线
    // - /Users/posva 当 sensitive: true,路由区分大小写
    { path: "/users/:id", sensitive: true },
    // 将匹配 /users, /Users, 以及 /users/42 而非 /users/ 或 /users/42/
    { path: "/users/:id?" },
  ],
  strict: true, // applies to all routes
});

3.4 可选参数

通过使用 ? 修饰符(0 个或 1 个)将一个参数标为可选:

const routes = [
  // 匹配 /users 和 /users/posva
  { path: "/users/:userId?" },
  // 匹配 /users 和 /users/42
  { path: "/users/:userId(\\d+)?" },
];

4. 嵌套路由

顶层的 router-view 渲染顶层路由匹配的组件。一个被渲染的组件也可以包含嵌套的 :

const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `,
};

要将组件渲染到嵌套的 router-view 中,需要在路由中配置 children,以 / 开头的嵌套路径将被视为根路径。不必使用嵌套的 URL:

const routes = [
  {
    path: "/user/:id",
    component: User,
    children: [
      {
        // 当 /user/:id/profile 匹配成功
        // UserProfile 将被渲染到 User 的 <router-view> 内部
        path: "profile",
        component: UserProfile,
      },
      {
        // 当 /posts 匹配成功
        // UserPosts 将被渲染到 User 的 <router-view> 内部
        path: "/posts",
        component: UserPosts,
      },
    ],
  },
];

如上配置,访问 /user/eduardo ,User 的 router-view 什么都不展示,因为没有匹配到嵌套路由。可以提供一个空的嵌套路径,来展示一些东西:

const routes = [
  {
    path: "/user/:id",
    component: User,
    children: [
      // 当 /user/:id 匹配成功
      // UserHome 将被渲染到 User 的 <router-view> 内部
      { path: "", component: UserHome },
 
      // ...其他子路由
    ],
  },
];

5. 编程式导航

除了  定义导航链接,还可以使用 router 的实例方法来导航。router.push 返回的是 Promise。

5.1 router.push 导航

使用 router.push 方法,会向 history 栈添加一个新的记录,所以,当点击浏览器后退按钮时,会回到之前的 URL。当点击  时,内部会调用这个方法,所以点击  相当于调用 router.push(...) :

// 字符串路径
router.push("/users/eduardo");
 
// 带有路径的对象
router.push({ path: "/users/eduardo" });
 
// 如果路由没有命名username参数,会报错,path: /user/:username?
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" });

使用 path 跳转 params 参数会无效,query 参数适用 path 或 name 跳转:

const username = "eduardo";
router.push(`/user/${username}`); // -> /user/eduardo
router.push({ path: `/user/${username}` }); // -> /user/eduardo
router.push({ name: "user", params: { username } }); // -> /user/eduardo
// `params` 不能与 `path` 一起使用
router.push({ path: "/user", params: { username } }); // -> /user

5.2 替换当前位置

不会向 history 添加新记录,直接取代了当前的路由。用法:

<script setup lang="ts">
import { useRouter } from "vue-router";
 
const router = useRouter();
router.push({ path: "/home", replace: true });
// 相当于
router.replace({ path: "/home" });
</script>
 
<template>
  <router-link :to="..." replace>
</template>

5.3 横跨历史

router.go(n) 用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于 window.history.go(n)。

// 向前移动一条记录,与 router.forward() 相同
router.go(1);
 
// 返回一条记录,与 router.back() 相同
router.go(-1);
 
// 前进 3 条记录
router.go(3);
 
// 如果没有那么多记录,静默失败
router.go(-100);
router.go(100);

6. 命名路由

使用 name 命名路由。优点:1. 没有硬编码的 URL。2. params 的自动编码/解码。3. 防止你在 url 中出现打字错误。4. 绕过路径排序(如显示一个)。

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

命名路由,通过 params 传递路由参数,如下路由将导航到 /user/erina。

<script setup lang="ts">
import { useRouter } from "vue-router";
 
const router = useRouter();
 
const handleGo = () =>
  router.push({ name: "user", params: { username: "erina" } });
</script>
 
<template>
  <router-link :to="{ name: 'user', params: { username: 'erina' } }">
    User
  </router-link>
  <div class="home" @click="handleGo">home</div>
</template>

7. 命名视图

设置多个同级,通过 name 属性确定渲染组件,默认 default:

<router-view class="view left-sidebar" name="LeftSidebar"></router-view>
<router-view class="view main-content"></router-view>
<router-view class="view right-sidebar" name="RightSidebar"></router-view>

多个视图就需要多个组件。正确配置 components (带上 s):

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: "/",
      components: {
        default: Home,
        // LeftSidebar: LeftSidebar 的缩写
        LeftSidebar,
        // 它们与 `<router-view>` 上的 `name` 属性匹配
        RightSidebar,
      },
    },
  ],
});

8. 重定向和别名

8.1 重定向

通过配置 redirect,实现路由重定向,当有 redirect 属性时,可以省略 component ,因为没有被访问,如下从 /home 重定向到 /:

const routes = [{ path: "/home", redirect: "/" }];

也可以使用 name 重定向:

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

使用一个方法,动态返回重定向目标:

const routes = [
  {
    // /search/screens -> /search?q=screens
    path: "/search/:searchText",
    redirect: (to) => {
      // 方法接收目标路由作为参数
      // return 重定向的字符串路径/路径对象
      return { path: "/search", query: { q: to.params.searchText } };
    },
  },
  {
    path: "/search",
    // ...
  },
];

8.2 别名

访问别名和访问路由一个效果,使用 alias 声明别名,以 / 开头,并可以使用数组提供多个别名:

const routes = [
  {
    path: "/",
    component: Homepage,
    alias: "/home",
  },
  {
    path: "/users",
    component: UsersLayout,
    children: [
      // 为这 3 个 URL 呈现 UserList
      // - /users
      // - /users/list
      // - /people
      { path: "", component: UserList, alias: ["/people", "list"] },
    ],
  },
];

9. 路由组件传参

在组件中使用 $route 会与路由紧密耦合,限制了组件的灵活性,因为它只能用于特定的 URL。可以通过 props 配置来解除这种行为:

const User = {
  template: "<div>User {{ $route.params.id }}</div>",
};
const routes = [{ path: "/user/:id", component: User }];
 
// 替换成
const User = {
  // 请确保添加一个与路由参数完全相同的 prop 名
  props: ["id"],
  template: "<div>User {{ id }}</div>",
};
const routes = [{ path: "/user/:id", component: User, props: true }];

9.1 命名视图

对于有命名视图的路由,必须为每个命名视图定义 props 配置:

const routes = [
  {
    path: "/user/:id",
    components: { default: User, sidebar: Sidebar },
    props: { default: true, sidebar: false },
  },
];

9.2 函数模式

创建一个返回 props 的函数。可以将参数转换为其他类型:

const routes = [
  {
    path: "/demo/:id?",
    name: "demo",
    component: Demo,
    props: (route) => {
      return { id: +route.params.id };
    },
  },
];

9.3 Via RouterView

<RouterView v-slot="{ Component }">
  <component
    :is="Component"
    view-prop="value"
   />
</RouterView>

10. 不同的历史模式

在创建路由器实例时,history 配置可以选择不同的历史模式。

10.1 Hash 模式

hash 模式是用 createWebHashHistory() 创建的,会在 url 后添加哈希字符(#),对 SEO 不友好,不推荐:

import { createRouter, createWebHashHistory } from "vue-router";
 
const router = createRouter({
  // /home#/
  history: createWebHashHistory(),
  routes: [
    //...
  ],
});

10.2 Memory 模式

Memory 模式是用 createMemoryHistory() 创建的,适合 Node 环境和 SSR,不推荐:

import { createRouter, createMemoryHistory } from "vue-router";
const router = createRouter({
  history: createMemoryHistory(),
  routes: [
    //...
  ],
});

10.3 HTML5 模式

用 createWebHistory() 创建 HTML5 模式,URL 会看起来很 "正常",推荐使用这个模式:

import { createRouter, createWebHistory } from "vue-router";
 
const router = createRouter({
  history: createWebHistory(),
  routes: [
    //...
  ],
});

Vue-Router 官网速通(下)https://developer.aliyun.com/article/1513245?spm=a2c6h.13148508.setting.26.f8774f0euyBLtl

目录
相关文章
|
23天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的成都锦城学院校内订餐系统附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的成都锦城学院校内订餐系统附带文章和源代码部署视频讲解等
37 7
|
1月前
|
前端开发
SASS 官方文档速通
SASS 官方文档速通
22 1
|
15天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的桂林旅游景点导游平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的桂林旅游景点导游平台附带文章源码部署视频讲解等
10 0
|
1月前
|
JavaScript 前端开发 API
Vue-Router 官网速通(下)
Vue-Router 官网速通(下)
15 0
|
1月前
|
存储 JavaScript API
Pinia 官网速通
Pinia 官网速通
9 0
|
1月前
|
JSON JavaScript 前端开发
axios 官网速通
axios 官网速通
16 0
|
1月前
|
存储 JSON 缓存
Vite 官方文档速通(下)
Vite 官方文档速通(下)
56 0
|
1月前
|
JSON 前端开发 JavaScript
Vite 官方文档速通(上)
Vite 官方文档速通(上)
48 0
|
1月前
|
JavaScript 前端开发 安全
Vue3官方文档速通(下)
Vue3官方文档速通(下)
42 0
|
1月前
|
JavaScript API
Vue3 官方文档速通(中)
Vue3 官方文档速通(中)
34 0