1. Динамическая маршрутизация
1.1 Динамическое сопоставление маршрутов
Маршрутизация делится на статическую маршрутизацию и динамическую маршрутизацию . Жестко закодированные маршруты, такие как «/login», упомянутые выше, являются статическими маршрутами.
Динамическая маршрутизация сопоставляет различную информацию с одним и тем же компонентом с помощью динамического поля (сокращение: параметр пути) в пути.
Например: есть компонент User, используемый для отображения всех пользователей, но идентификаторы этих пользователей разные.
# User.vue
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
console.log(router.params)
</script>
<template>
<div>
{
{ $route.params.id }}
</div>
</template>
import { createRouter, createWebHistory } from 'vue-router'
import Login from '@/views/Login.vue'
const routes = [
{
path: '/',
redirect: '/Login'
},
{
path: '/login',
name: 'login',
component: Login,
meta: {
title: '登录',
requiresAuth: false // 设置为 false 或 不设置代表不需要校验身份,任何人都可以访问这个页面
}
},
{
path: '/user/:id',
name: 'user',
component: () => import('@/views/User.vue'),
meta: {
title: '用户管理', // 页面标题
requiresAuth: true // 登录身份校验成功,才可以访问这个页面
}
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
router.beforeEach((to, from) => {
if(to.meta.title) document.title = to.meta.title
})
export default router
- meta Метаинформация маршрутизации : ее можно использовать для присоединения к маршруту любой информации, такой как имя перехода, полномочия маршрутизации доступа, заголовок страницы и т. д. Можно получить доступ через адреса маршрутизации или навигационные охранники.
- router.beforeEach((to,from) => {}) регистрирует глобальную защиту beforeEach, которая будет выполняться перед каждой навигацией.
- к цели, которая вот-вот войдет
- from Маршрут, по которому уходит текущая навигация
- Параметры пути
:
обозначаются двоеточиями.$route.params
При сопоставлении маршрута значение его параметров будет отображаться в каждом компоненте в виде файла .
1.2 Другой метод настройки динамической маршрутизации
Динамические параметры можно настроить через дочерние элементы
const routes = [
// ...其它路由参数
{
path: '/user',
name: 'user',
children: [
{
path: ':id',
component: () => import('@/views/User.vue'),
meta: {
title: '用户管理',
requiresAuth: true
},
},
{
path: 'Add',
component: () => import('@/views/UserAdd.vue'),
meta: {
title: '用户新增',
requiresAuth: true
}
}
]
}
]
- Вложенные пути, начинающиеся с,
/
будут рассматриваться как корневые пути. Это позволяет вам использовать преимущества вложенности компонентов без использования вложенных URL-адресов.
1.3 Согласование грамматики маршрутизации — пользовательская регуляризация в параметрах
Два маршрута /:orderId
и /:productName
оба будут соответствовать одному и тому же URL-адресу, поэтому нам нужен способ отличить их друг от друга.
Предположение: orderId
всегда число и productName
может быть что угодно, поэтому мы можем указать пользовательское регулярное выражение для параметра в скобках.
const routes = [
// /:orderId -> 仅匹配数字
{ path: '/:orderId(\\d+)' },
// /:productName -> 匹配其他任何内容
{ path: '/:productName' },
]
В этом случае переход к /25
будет соответствовать /:orderId
, а остальные случаи будут соответствовать /:productName
.
Обязательно избегайте обратной косой черты ( \
) , как мы это делали для \d
(становиться \\d
), чтобы фактически передать символ обратной косой черты в строке в JavaScript.
Подробнее о синтаксисе сопоставления маршрутизации см. на официальном сайте Vue Router .
1.4 API для добавления, удаления и изменения маршрутов
Добавление маршрутов обычно выполняется с помощью routes
options , но в некоторых случаях вы можете добавить или удалить маршруты, когда приложение уже запущено:
- Добавить маршрутизацию router.addRoute()
- Удалить маршрут router.removeRoute()
// 添加路由
router.addRoute({ path: '/about', component: About })
// 我们也可以使用 this.$route 或 route = useRoute() (在 setup 中)
router.replace(router.currentRoute.value.fullPath)
// 删除路由
router.removeRoute('about')
Если вам нужно дождаться появления новых маршрутов, вы можете использовать
await router.replace()
2. Именование представлений
Если вы хотите определить несколько представлений на одном уровне в одном и том же интерфейсе, вам нужно установить router-view
имя для (по умолчанию по умолчанию), чтобы вы могли иметь несколько выходов.
<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: createWebHashHistory(),
routes: [
{
path: '/',
components: {
default: Home,
// LeftSidebar: LeftSidebar 的缩写
LeftSidebar,
// 它们与 `<router-view>` 上的 `name` 属性匹配
RightSidebar,
},
},
],
})
Более продвинутые вложенные именованные представления выглядят следующим образом, вы можете попробовать проанализировать и написать код самостоятельно:
/settings/emails /settings/profile
+-----------------------------------+ +------------------------------+
| UserSettings | | UserSettings |
| +-----+-------------------------+ | | +-----+--------------------+ |
| | Nav | UserEmailsSubscriptions | | +------------> | | Nav | UserProfile | |
| | +-------------------------+ | | | +--------------------+ |
| | | | | | | | UserProfilePreview | |
| +-----+-------------------------+ | | +-----+--------------------+ |
+-----------------------------------+ +------------------------------+
Nav
Просто обычный компонент.UserSettings
является компонентом представления.UserEmailsSubscriptions
,UserProfile
,UserProfilePreview
являются вложенными компонентами представления.
3 Передача параметров компонента маршрутизации
В компонентах проекта с маршрутизацией использование $route будет тесно связано с маршрутизацией, что ограничивает гибкость компонента, делая его доступным только для определенных URL-адресов.
Если вы хотите удалить это поведение, вы можете настроить его через реквизиты
3.1 Значение атрибута route props равно true
# 路由配置代码
{
path: '/user',
name: 'user',
component: () => import('@/views/User.vue'),
children: [
{
path: ':id',
component: () => import('@/views/UserHome.vue'),
// 路由配置 props:true,这样映射的组件中可以通过 props 定义对应的路由参数,从而达到$route对象和组件解耦的效果
props: true
}
]
}
# 路由映射组件代码
<script setup>
import { defineProps } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
// 组件 props 中定义路由参数对应的属性
const props = defineProps(['id'])
</script>
<template>
<div>
// 通过 $route 对象调用路由参数
<em> {
{ $route.params.id }} </em>
<br>
// 通过 props 中定义的属性调用路由参数
<strong>{
{ props.id }}</strong>
</div>
</template>
- Когда для свойства конфигурации маршрута
props
установлено значениеtrue
,route.params
оно будет установлено как реквизит компонента.- Преимущество передачи параметров компонентам маршрутизации заключается в упрощении повторного использования и тестирования компонентов.
Если маршрут содержит именованные представления, вы должны определить конфигурацию свойств для каждого именованного представления:
const routes = [
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
3.2 Значение атрибута реквизитов маршрутизации является общим объектом
Когда props
это объект, он устанавливается как есть в свойствах компонента. Полезно, когда реквизит статичен.
# 路由代码
{
path: '/user',
name: 'user',
component: () => import('@/views/User.vue'),
children: [
{
path: ':id',
component: () => import('@/views/UserHome.vue'),
// props 是一个对象,会将这个对象传递给对应的组件。props 中无法获取路由参数
props: { num: 1234567890 }
}
]
}
# 映射组件的代码
<script setup>
import { defineProps } from 'vue'
const props = defineProps(['id', 'num'])
console.log(props, 11111111111) //Proxy(Object) {num: 1234567890, id: undefined} 11111111111
</script>
<template>
<div>
<em> {
{ $route.params.id }} </em>
<br>
<strong>{
{ props.id }}</strong> <!-- props 中无法获取路由参数 -->
<hr>
<ins>{
{ props.num }}</ins>
</div>
</template>
3.4 Значение атрибута route props является функцией
Вы можете создать функцию, которая возвращает свойства. Это позволяет вам приводить параметры к другим типам, комбинировать статические значения со значениями на основе маршрута и т. д.
const routes = [
{
path: '/search',
component: SearchUser,
props: route => ({ query: route.query.q })
}
]
URL-адрес /search?q=vue
будет передан компоненту {query: 'vue'}
в качестве реквизита .SearchUser
4. режим истории истории
history
Конфигурация позволяет нам выбирать между различными режимами истории при создании экземпляра маршрутизатора .
-
Хэш-режим
Шаблоны хешей
createWebHashHistory()
создаются с конфигурацией сервера и не зависят от нее. Но он не будет обрабатываться поисковыми системами, да и SEO-эффект плохой.import { createRouter, createWebHashHistory } from 'vue-router' const router = createRouter({ history: createWebHashHistory(), routes: [ //... ], })
createWebHashHistory(base?)
Параметр представляет собой путь// 基于 https://example.com/folder 的 hash 模式 createWebHashHistory() // 给出一个 `https://example.com/folder#` 的 URL createWebHashHistory('/folder/') // 给出一个 `https://example.com/folder/#` 的 URL
-
режим HTML5
Создан в режиме HTML5
createWebHistory()
, требует правильно настроенного сервера. Этот метод будет обрабатываться поисковыми системами, и SEO-эффект лучше. Это наиболее распространенный шаблон для одностраничных приложений.index.html
Если URL-адрес не соответствует каким-либо статическим ресурсам, он должен обслуживать ту же страницу , что и в вашем приложении . Примеры конфигурации для каждого сервераimport { createRouter, createWebHistory } from 'vue-router' const router = createRouter({ history: createWebHistory(), routes: [ //... ] })
При использовании этого режима истории URL-адреса будут выглядеть «нормально», например
https://example.com/user/id
.
Универсальный маршрутизатор отображает страницу 404:
const router = createRouter({
history: createHistory(),
routes: [{ path: '/:pathMatch(.*)', component: NotFoundComponent }]
})
5 маршрутный охранник
Vue Router предоставляет различные средства защиты маршрутизации, такие как глобальные средства защиты маршрутизации, средства защиты маршрутизации компонентов или средства защиты отдельных маршрутов. В основном они охраняют навигацию, прыгая или отменяя.
5.1 Глобальная передняя защита
Глобальные предохранители регистрируются через router.beforeEach(callback(to, from)). Parameters — это защищенный метод, который принимает два параметра:
- к цели, которая вот-вот войдет
- from Маршрут, по которому уходит текущая навигация
Когда срабатывает навигация, глобальные передние охранники вызываются в порядке их создания. Guards разрешаются асинхронно, и навигация ожидает разрешения всех Guards.
Значения, которые можно вернуть:
-
false : используется для отмены текущей навигации.
const router = createRouter({ ... }) router.beforeEach((to, from) => { // ... // 返回 false 以取消导航 return false })
-
Адрес маршрутизации : так же, как и при вызове router.push(), вы можете перейти к указанному адресу маршрутизации и указать этот адрес маршрутизации в возвращаемом объекте с помощью таких атрибутов, как: replace: true или name: 'home'.
router.beforeEach(async (to, from) => { if ( // 检查用户是否已登录 !isAuthenticated && // 避免无限重定向 to.name != 'Login' ) { // 将用户重定向到登录页面 return { name: 'Login' } } })
router.beforeEach(async (to, from) => { // canUserAccess() 返回 `true` 或 `false` const canAccess = await canUserAccess(to) if (!canAccess) return '/login' })
5.2 Защита глобального анализа
Глобальные охранники разрешения регистрируются через router.beforeResolve. Защита разрешения вызывается непосредственно перед подтверждением каждой навигации и после того, как все встроенные защиты и компоненты с асинхронной маршрутизацией были разрешены .
5.3 Глобальные постхуки
Почтовые крючки не изменяют саму навигацию. Полезно для специальных возможностей, таких как аналитика, изменение заголовков страниц, объявление страниц и многое другое.
5.4 Эксклюзивная защита маршрутизации
Охранник beforeEnter может быть настроен непосредственно на маршруте и срабатывает только при входе на маршрут . Он не будет запущен при изменении параметров, запроса и хэша.
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
// 返回 false 用于取消当前导航
return false
}
}
]
Охранник beforeEnter также может быть массивом функций.
5.5 Ограждения внутри компонентов
Как следует из названия, защита маршрута определяется непосредственно в компоненте, который будет передан в конфигурацию маршрута.
Компоненты маршрутизации могут добавлять следующие средства защиты (настройка составного API):
-
onBeforeRouteUpdate вызывается при изменении текущего маршрута и повторном использовании компонента.
Например, для пути с динамическими параметрами при переходе между и
/users/:id
, поскольку будет отображаться один и тот же компонент, экземпляр компонента будет использоваться повторно. И этот хук будет вызываться в этом случае./users/1
/users/2
UserDetails
-
onBeforeRouteLeave вызывается, когда навигация покидает маршрут, соответствующий отображаемому компоненту.
Эта защита выхода обычно используется для предотвращения внезапного ухода пользователей без сохранения изменений. Эту навигацию можно отменить
false
, .
Образец кода:
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
import { ref } from 'vue'
// 与 beforeRouteLeave 相同,无法访问 `this`
onBeforeRouteLeave((to, from) => {
const answer = window.confirm('确定要离开当前页面? 你并未保存更改信息哦!')
// 取消导航并停留在同一页面上
if (!answer) return false
})
const userData = ref()
// 与 beforeRouteUpdate 相同,无法访问 `this`
onBeforeRouteUpdate(async (to, from) => {
//仅当 id 更改时才获取用户,例如仅 query 或 hash 值已更改
if (to.params.id !== from.params.id) {
userData.value = await fetchUser(to.params.id)
}
})
5.6 Полный процесс анализа навигации
- Навигация запущена.
- Вызов охранников в деактивированных компонентах
onBeforeRouteLeave
. - Вызовите глобальную
beforeEach
охрану. onBeforeRouteUpdate
Вызов охранников (2.2+) в многоразовых компонентах .- Вызывается в конфигурации маршрутизации
beforeEnter
. - Разобрать компоненты асинхронной маршрутизации.
- Вызывается в активированном компоненте
beforeRouteEnter
(необязательный API). - Вызывает глобальную
beforeResolve
стражу (2.5+). - Навигация подтверждена.
- Вызов глобального
afterEach
хука. - Запускает обновление DOM.
- Вызовите функцию обратного вызова
beforeRouteEnter
, переданную в Guard (необязательный API)next
, и экземпляр созданного компонента будет передан в качестве параметра функции обратного вызова.
Примечание. Все средства защиты маршрутизации будут удалены при удалении компонента.