Vue3 Router

1. 定义 404 路由

当URL地址上的路径不能匹配到对应的路由时,可设置404路由界面。

router/index.js

// router/index.js
import { createRouter, createWebHashHistory } from 'vue-router';

import Home from '../views/Home';
import NotFound from '../views/not-found';

const routes = [
  { path: '/home', component: Home, name: 'Home' },
  // 404页面
  { path: '/:pathmatch(.*)', component: NotFound }
];
const router = createRouter({
  // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
  history: createWebHashHistory(),
  routes // `routes: routes` 的缩写
});

export default router;

对应的404-Vue界面:

not-found.vue

<template>
  <div>
    <h2>404,该页面未找到</h2>
    <!-- $route.params.pathmatch为相应未正常匹配的路径 -->
    <!-- 如:http://localhost:8080/#/abc/fct,对应的template为:abc/fct -->
    <!-- 如若定义路由时path是'/:pathmatch(.*)*',则template展示为:['abc', 'fct'] -->
    <h4>路径: {{ $route.params.pathmatch }}可能有误!</h4>
    
  </div>
</template>

<script setup></script>

<style lang="scss" scoped></style>

2.<router-link>组件

使用 router-link 组件进行导航。

2.1.1 to

表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个 string 或者是描述目标位置的对象

<!-- 字符串 -->
<router-link to="/home">Home</router-link>
<!-- 渲染结果 -->
<a href="/home">Home</a>

<!-- 使用 v-bind 的 JS 表达式 -->
<router-link :to="'/home'">Home</router-link>

<!-- 同上 -->
<router-link :to="{ path: '/home' }">Home</router-link>

<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: '123' }}">User</router-link>

<!-- 带查询参数,下面的结果为 `/register?plan=private` -->
<router-link :to="{ path: '/register', query: { plan: 'private' }}">
  Register
</router-link>

2.1.2 replace

设置 replace 属性的话,当点击时,会调用 router.replace(),而不是 router.push(),所以导航后不会留下历史记录。

<router-link to="/home" replace></router-link>

2.1.3 active-class

默认值:"router-link-active"

链接激活时(浏览器Url地址匹配后,会自动给a标签加上该class),应用于渲染的 <a> 的 class。

2.1.4 exact-active-class

默认值:"router-link-exact-active"

链接精准激活时(url地址精准匹配后),应用于渲染的 <a> 的 class。

2.1.5 aria-current-value

当链接激活时,传递给属性 aria-current 的值。

2.1.6 custom

vue2的路由,可以使用tag属性更改包裹的元素。而vue3使用的VueRouter4,废弃了该属性。

<router-link> 是否应该将其内容包裹在 <a> 元素中。在使用 v-slot 创建自定义 RouterLink 时很有用。默认情况下,<router-link> 会将其内容包裹在 <a> 元素中,即使使用 v-slot 也是如此。传递自定义的 prop,可以去除这种行为。

<template>
  <nav>
    <router-link to="/" custom>
      <button>Home</button>
    </router-link>
    |
    <router-link to="/about">
      <button>About</button>
    </router-link>
  </nav>
  <!-- 实际渲染 -->
<!-- 
   <nav>
    <button>Home</button>
    |
    <a href="#/about" class="">
      <button>About</button>
    </a>
  </nav> 
-->
  <router-view />
</template>

<router-link> 通过一个作用域插槽暴露底层的定制能力。

<router-link to="/about" custom v-slot="{ href, route, navigate, isActive, isExactActive }">
  <!-- href: #/about -->
  <p>href: {{ href }}</p>
  <!-- route: 当前route对象 -->
  <p>route: {{ route }}</p>
  <!-- navigate函数进行路由跳转 -->
  <button @click="navigate">navigate函数跳转</button>
  <!-- isActive: 是否激活 -->
  <p>isActive: {{ isActive }}</p>
  <!-- isExactActive: 是否精准激活 -->
  <p>isExactActive: {{ isExactActive }}</p>
</router-link>

2.2.1 作用域插槽提供的对象:

  • href:解析后的 URL。将会作为一个 <a> 元素的 href 属性。如果什么都没提供,则它会包含 base
  • route:跳转的route的对象。
  • navigate:触发导航的函数。 会在必要时自动阻止事件,和 router-link 一样。例如:ctrl 或者 cmd + 点击仍然会被 navigate 忽略。
  • isActive:当前路由是否被激活,激活则为 true。可配置应用 class。
  • isExactActive:当前路由是否被精准激活,激活则为 true。可配置应用 class。

2.2.2 将激活的 class 应用在外层元素

有时我们可能想把激活的 class 应用到一个外部元素而不是 <a> 标签本身,这时你可以在一个 router-link 中包裹该元素并使用 v-slot 属性来创建链接:

<router-link
  to="/foo"
  custom
  v-slot="{ href, route, navigate, isActive, isExactActive }"
>
  <li
    :class="[isActive && 'router-link-active', isExactActive && 'router-link-exact-active']"
  >
    <a :href="href" @click="navigate">{{ route.fullPath }}</a>
  </li>
</router-link>

3. <router-view>组件

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

3.1 <router-view> Props

3.1.1 name

  • 类型string
  • 默认值"default"

如果 <router-view> 设置了 name,则会渲染对应的路由配置中 components 下的相应组件。

用于命名视图

3.1.2 route

一个路由地址的所有组件都已被解析(如果所有组件都被懒加载),因此可以显示。

3.2 <router-view> 的插槽

主要用于给路由匹配成功后展示的组件进行额外包裹,如:<transition><keep-alive> 组件。

保持缓存或添加动画:

<router-view v-slot="{ Component, route }">
  <transition name="fct">
    <keep-alive>
      <suspense>
        <template #default>
          <component :is="Component" />
        </template>
        <template #fallback> Loading... </template>
      </suspense>
    </keep-alive>
  </transition>
</router-view>
  • Component: VNodes(路由匹配成功后,展示的组件实例), 传递给 <component>is prop。
  • route: 解析出的标准化route对象。

4. 动态路由

动态路由主要通过两个函数实现。router.addRoute()router.removeRoute()。它们注册一个新的路由,也就是说,如果新增加的路由与当前位置相匹配,就需要你用 router.push()router.replace()手动导航,才能显示该新路由。

4.1 添加路由

对路由的添加通常是通过 routes 选项来完成的,但是在某些情况下,你可能想在应用程序已经运行的时候添加或删除路由。

router.addRoute({ path: '/about', component: About })

4.2 删除路由

有几个不同的方法来删除现有的路由:

  • 通过添加一个名称冲突的路由。如果添加与现有途径名称相同的途径,会先删除路由,再添加路由:

    router.addRoute({ path: '/about', name: 'about', component: About })
    // 这将会删除之前已经添加的路由,因为他们具有相同的名字且名字必须是唯一的
    router.addRoute({ path: '/other', name: 'about', component: Other })
    
  • 通过调用router.addRoute()返回的回调:

    const removeRoute = router.addRoute(routeRecord)
    removeRoute() // 删除路由如果存在的话
    

    当路由没有名称时,这很有用。

  • 通过使用router.removeRoute()按名称删除路由:

    router.addRoute({ path: '/about', name: 'about', component: About })
    // 删除路由
    router.removeRoute('about')
    

    需要注意的是,如果你想使用这个功能,但又想避免名字的冲突,可以在路由中使用Symbol作为名字。

当路由被删除时,所有的别名和子路由也会被同时删除

4.3 添加嵌套路由

要将嵌套路由添加到现有的路由中,可以将路由的 name 作为第一个参数传递给 router.addRoute(),这将有效地添加路由,就像通过 children 添加的一样:

router.addRoute({ name: 'admin', path: '/admin', component: Admin })
router.addRoute('admin', { path: 'settings', component: AdminSettings })

这等效于:

router.addRoute({
  name: 'admin',
  path: '/admin',
  component: Admin,
  children: [{ path: 'settings', component: AdminSettings }],
})
posted @ 2022-11-01 11:40  青柠i  阅读(142)  评论(0编辑  收藏  举报