💡简介
来自官网 https://router.vuejs.org/zh/guide/
Vue 让我们用组件组成了应用,而 Vue Router 又能将组件映射到路由上。
router.js
创建路由,同时将组件映射到路由上main.js
引入router.js
,并app.use(router)
在模板中使用,用到了两个组件
<router-view>
和<router-link>
<nav>
<!-- 使用 router-link 组件进行导航 -->
<!-- 通过传递 `to` 来指定链接 -->
<!-- `<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</nav>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
1. 动态路由
在路径中使用一个动态字段(路径参数),路径参数用 :
表示,其值可通过 $route.params
来访问。比如:
/users/:id
/users/:username
/users/:username/posts/:postId
1.1 参数变化时
当动态参数发生变化时,相同的组件实例会被重复利用(比起销毁再重建更高效),这就意味着组件的生命周期钩子不会被调用。
1.2 相应参数变化
此时如果要响应同一个组件中的参数变化,可以有以下办法:
watch
this.$route
对象的任意属性Vue3 在
setup
里没有this
,所以是使用useRouter
,useRoute
函数
使用组件内导航守卫
beforeRouteLeave
,beforeRouteUpdate
Vue3 用了组合式 API,所以是
onBeforeRouteLeave
,onBeforeRouteUpdate
组合式函数 API
<router-view :key="$route.path">
是强制刷新组件(先 destroy 再 re-render)
import { useRouter, useRoute, onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
const router = useRouter()
const route = useRoute() // 避免监听整个 route 对象,应该直接监听期望改变的参数
// 在模板中可以访问 $router 和 $route
2. 嵌套路由
要将组件渲染到嵌套的 router-view
中,就需要在路由中配置 children
。
几个
children
就应该有几个<RouterView />
空的嵌套路径,也很有用,
{ path: '' }
通常会给路由命名,使用方便,
name
属性跳转,跳父路由 vs 跳子路由
以 /
开头的嵌套路径将被视为根路径,这将允许我们利用组件嵌套,而不必使用嵌套的 URL。
3. 路由守卫
Navigation Guards
场景:普通路由、动态路由(对参数有效性的校验)
用途:需要登录的页面、NotFoundPage,详见文末示例
路由守卫的几种方式:
全局
xxx
4. 历史模式
History mode:HTML5 模式 vs Hash 模式
HTML5 web history API,Single Page App
/#/home
传统的 server side apps
5. 性能方面
5.1 懒加载(动态导入)
表现是最终打包的资源是否分包 ,写法是 dynamic import 路由的组件。
对应内容:bundle 源代码,每个 page 都有它自己的 chunk/file/bundle。
Vite 的 code splitting 特性
开发模式下,Vite 没有 bundle 代码,直接用的浏览器原生的 import
Webpack 的 code splitting 特性
在 Vue 中可以用 magic comment 给每个组件对应的小 bundles 命名
5.2 路由的草稿功能
切换路由时,保持草稿功能
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
6. 更多
6.1 更多特性
命名路由:没有硬编码的 URL、绕过路径排序
<router-link :to="{name: 'user'}">
router.push({name: 'user'})
路由的
redirect
和alias
。很实用的样子,详见下方示例给路由传参:
props
属性路由的匹配语法
静态路由
动态路由
也可以使用正则表达式
{ path: '/xx/:id(\\d+)' }
动态增加路由,用脚本 add/remove 的 route record(比如某些插件)
从整体配置哪些路由要特定组件(比如页面广告)
Named View,
<router-view name="xxx"></router-view>
路由配置用了
components
属性,而不是component
路由组件切换时
动画:全局 Vue 组件
<transition><transition>
滚动行为,
scrollBehavior
属性
<!-- Vue2 动画 -->
<transition>
<router-view></router-view>
<transition>
<!-- Vue3 动画 -->
<router-view v-slot="{Component}">
<!-- name 指定 css 的类名, slide | moveUp | fade, back-in -->
<transition name="slide" mode="out-in">
<component :is="Component"></component>
</transition>
</router-view>
6.2 注意事项
<RouterLink>
vs<a>
前者只刷新路由组件,它会拦截 click 事件。适合内部链接
后者会 reload 整个页面,适合外部链接
当前选中的路由,有类名
.router-link-acitive
,也可以用linkActiveClass
自定义路由跳转
在模板里用
<router-link>
在脚本里用
$router.push
,$router.replace
。不同之处是如何影响路由历史
route
的fullPath
和path
fullPath
包括 path, query, hashpath
包括 path
components
文件夹放整个 App 的组件,若是某个 page 的则放自己views/page/components
监测路由失败
import { isNavigationFailure, NavigationFailureType } from 'vue-router'
失败的原因可能如下图
7. 示例
const routes = [
{
path: '/',
component: () => import('@/views/HomeView.vue'),
children: [
{
path: '',
alias: ['/home', '/search'],
name: 'ResultList',
component: () => import('@/views/home/ResultListView.vue')
},
{
path: 'preview/:id',
name: 'CardPreview',
component: () => import('@/views/home/CardPreview.vue')
},
{
path: 'feature/:cat',
name: 'FeatureList',
component: () => import('@/views/home/FeatureView.vue'),
beforeEnter: (to, from) => {
const cat = to.params.cat
if (cat === 'html' || cat === 'css') {
} else {
return { name: 'NotFound' }
}
}
}
]
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/LoginView.vue')
},
{
path: '/admin',
component: () => import('@/views/AdminView.vue'),
meta: {
requiresAuth: true
},
children: [
{
path: '',
name: 'AdminList',
component: () => import('@/views/admin/ListView.vue')
},
{
path: 'card',
name: 'AdminCard',
component: () => import('@/views/admin/CardView.vue')
}
]
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('@/views/NotFound.vue')
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
方法
install()
isReady()
onError()
错误处理程序
back
: () => go(-1)forward
: () => go(1)go()
push()
replace()
beforeResolve()
导航守卫beforeEach()
导航守卫afterEach()
导航钩子
getRoutes()
路由记录的完整列表hasRoute()
resolve()
返回路由地址的标准化版本
addRoute()
动态添加/删除路由removeRoute()
属性
currentRoute
options
listening
__hasDevtools
最重要的是了解原理,因为具体的写法和某些约定可能会变(知识本身在更新)。
深入的:原理、实现
宽泛的:有几种方式,它们的适用场景和特点
有关路由的详细参数,详见 Vue Router API 参考。
Last updated