[Экология Vue3] Базовые знания о маршрутизации VueRouter

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
  1. meta Метаинформация маршрутизации : ее можно использовать для присоединения к маршруту любой информации, такой как имя перехода, полномочия маршрутизации доступа, заголовок страницы и т. д. Можно получить доступ через адреса маршрутизации или навигационные охранники.
  2. router.beforeEach((to,from) => {}) регистрирует глобальную защиту beforeEach, которая будет выполняться перед каждой навигацией.
    • к цели, которая вот-вот войдет
    • from Маршрут, по которому уходит текущая навигация
  3. Параметры пути :обозначаются двоеточиями. $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
        		}
        	}
        ]
    }
]
  1. Вложенные пути, начинающиеся с, /будут рассматриваться как корневые пути. Это позволяет вам использовать преимущества вложенности компонентов без использования вложенных 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 для добавления, удаления и изменения маршрутов

Добавление маршрутов обычно выполняется с помощью routesoptions , но в некоторых случаях вы можете добавить или удалить маршруты, когда приложение уже запущено:

  1. Добавить маршрутизацию router.addRoute()
  2. Удалить маршрут 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>
  1. Когда для свойства конфигурации маршрута propsустановлено значение true, route.paramsоно будет установлено как реквизит компонента.
  2. Преимущество передачи параметров компонентам маршрутизации заключается в упрощении повторного использования и тестирования компонентов.

Если маршрут содержит именованные представления, вы должны определить конфигурацию свойств для каждого именованного представления:

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/2UserDetails

  • 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 Полный процесс анализа навигации

  1. Навигация запущена.
  2. Вызов охранников в деактивированных компонентах onBeforeRouteLeave.
  3. Вызовите глобальную beforeEachохрану.
  4. onBeforeRouteUpdateВызов охранников (2.2+) в многоразовых компонентах .
  5. Вызывается в конфигурации маршрутизации beforeEnter.
  6. Разобрать компоненты асинхронной маршрутизации.
  7. Вызывается в активированном компоненте beforeRouteEnter(необязательный API).
  8. Вызывает глобальную beforeResolveстражу (2.5+).
  9. Навигация подтверждена.
  10. Вызов глобального afterEachхука.
  11. Запускает обновление DOM.
  12. Вызовите функцию обратного вызова beforeRouteEnter, переданную в Guard (необязательный API) next, и экземпляр созданного компонента будет передан в качестве параметра функции обратного вызова.

Примечание. Все средства защиты маршрутизации будут удалены при удалении компонента.

Guess you like

Origin blog.csdn.net/qq_39335404/article/details/131498394