vue路由的基本使用
vue-router简介
Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。功能包括:
- 嵌套路由映射
- 动态路由选择
- 模块化、基于组件的路由配置
- 路由参数、查询、通配符
- 展示由 Vue.js 的过渡系统提供的过渡效果
- 细致的导航控制
- 自动激活 CSS 类的链接
- HTML5 history 模式或 hash 模式
- 可定制的滚动行为
- URL 的正确编码
一、路由配置和使用
1、安装
打开项目终端,通过npm安装
npm install vue-router@4
2、创建路由实例
在项目中src目录想创建Router文件夹,新建index.js文件,在这个文件下配置路由:
import { createWebHashHistory, createRouter } from 'vue-router'
import Center from '../view/Center.vue' //引入组件路径(路由组件尽量放在view文件夹下)
import Home from '../view/Home.vue'
const routes = [
{
path: '/Center', //跳转的路径
name:'Center ' //命名路由,也可以不写
component: Center //跳转到对应的组件
},
{
path: '/Home',
component: Home
},
]
const router = createRouter({
history: createWebHashHistory(),//hash的模式,如#/home,#/center 带#号的路径
// history: createWebHistory(),//web的模式,如/home,/center 不带#号的路径
routes,//`routes:routes`的缩写
})
export default router
2、在组件中引用路由 router-view ,如APP根组件中直接引用:
<template>
app
<!--插槽-->
<router-view></router-view>
</template>
3、最后还需要把路由挂载到APP实例中,在main.js中注册路由:
import { createApp } from 'vue'
import App from './App.vue'
import router from './Router' //直接导入Router文件夹,会自动找到index.js这个文件
const app=createApp(App)
app.use(router) //注册路由插件
app.mount('#app')
直接输入对应的路径,显示对应的组件,到此路由的基本模型已经做好了
二、路由重定向与别名
- 重定向也是通过 routes 配置redirect来完成,下面例子是从 /home 重定向到 /:
const routes = [
{
path: '/home',
redirect: '/'
}
]
- 重定向的目标也可以是一个命名的路由:(路由通过name来命名)
const routes = [{ path: '/home', redirect: { name: 'center' } }]
- 常规参数只匹配url片段之间的字符,用 / 分割。如果我们想匹配任意路径,我们可以自定义的路径参数正则表达式,在路径参数后面的括号中加入 正则表达式:
const routes = [
{
path: '/:pathMatch(.*)*', //pathMatch只是占位符,任意字母都可以
name:'NotFound',
component: NotFound
},
]
- 别名用alias属性表示,当url匹配到别名/abc,也会跳转到组件center中去
const routes = [
{
path: '/Center',
component: Center ,
alias:'/abc' //注意别名有个/;也可以用数组alias: ['/abc', 'aaa']
},
]
三、声明式导航
1、传统的导航
通过a标签跳转
<div class="tabbar">
<ul>
<li><a href="#/home">首页</a></li>
<li><a href="#/films">影院</a></li>
<li><a href="#/center">我的</a></li>
</ul>
</div>
2、通过路由router-link
- to跳转到对应的路由,不需要加#号
- 不过标签会带a标签的样式,底部会有个下划线不太好看,后面我们也可以通过$route.push跳转的方法
<ul>
<li><router-link to="/home">首页</router-link> </li>
<li><router-link to="/films">影院</router-link> </li>
<li><router-link to="/center">我的</router-link></li>
</ul>
- 通过active-class="kerwin"来命名,使选中的显示高亮
<template>
<div class="tabbar">
<ul>
<li>
<router-link to="/home" active-class="kerwin">首页</router-link>
</li>
<li>
<router-link to="/films" active-class="kerwin">影院</router-link>
</li>
<li>
<router-link to="/center" active-class="kerwin">我的</router-link>
</li>
</ul>
</div>
</template>
<script setup>
</script>
<style scoped>
.kerwin{
color: red;
}
.tabbar{
position: fixed;
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
bottom: 10px;
}
.tabbar ul{
display: flex;
}
.tabbar ul li{
flex:1;
}
</style>
如图所示:
四、嵌套路由
一个路由组件下面,再嵌套路由,要将组件渲染到这个嵌套的 router-view 中,我们需要在路由中配置 children:
const routes = [
{
path: '/user',
component: User,
children: [
{
// 当 /user/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
// path: '/user/profile'的简写,通过http://localhost:5173/#/user/profile访问
component: UserProfile,
},
{
// 当 /posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: '/posts', //注:可以通过http://localhost:5173/#/posts访问
component: UserPosts,
},
],
},
]
注意,以 / 开头的嵌套路径将被视为根路径。这允许你利用组件嵌套,而不必使用嵌套的 URL。
五、编程式导航
- router 指代路由器实例。在组件内部,你可以使用
$router
属性访问路由,例如
this.$router.push(...)
。如果使用组合式 API,你可以通过调用useRouter()
来访问路由器。
声明式 | 编程式 |
---|---|
< router-link :to=“…” > | router.push(…) |
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
const username = 'eduardo'
// 我们可以手动建立 url,但我们必须自己处理编码
router.push(`/user/${username}`) // -> /user/eduardo
// 同样
router.push({ path: `/user/${username}` }) // -> /user/eduardo
// 如果可能的话,使用 `name` 和 `params` 从自动 URL 编码中获益
router.push({ name: 'user', params: { username } }) // -> /user/eduardo
// `params` 不能与 `path` 一起使用
router.push({ path: '/user', params: { username } }) // -> /user
- 替换当前位置
直接在传递给 router.push 的 to 参数中增加一个属性 replace: true :
router.push({ path: '/home', replace: true })
// 相当于
router.replace({ path: '/home' })
- 横跨历史
该方法采用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于 window.history.go(n)。
// 向前移动一条记录,与 router.forward() 相同
router.go(1)
// 返回一条记录,与 router.back() 相同
router.go(-1)
// 前进 3 条记录
router.go(3)
// 如果没有那么多记录,静默失败
router.go(-100)
router.go(100)
六、动态路由匹配
很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但用户 ID 不同。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数 :
import User from './User.vue'
// 这些都会传递给 `createRouter`
const routes = [
// 动态字段以冒号开始
{ path: '/users/:id', component: User }, //id属于占位符
]
路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 route.params
的形式暴露出来。因此,我们可以通过更新 User 的模板来呈现当前的用户 ID:
<template>
<div>
<!-- 当前路由可以通过 $route 在模板中访问 -->
User {{ $route.params.id }}
</div>
</template>
要对同一个组件中参数的变化做出响应的话,你可以简单地 watch $route 对象上的任意属性,在这个场景中,就是$route.params
:
<script setup>
import { watch } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
watch(() => route.params.id, (newId, oldId) => {
// 对路由变化做出响应...
})
</script>
或者,使用 beforeRouteUpdate 导航守卫,它还允许你取消导航:
<script setup>
import { onBeforeRouteUpdate } from 'vue-router'
// ...
onBeforeRouteUpdate(async (to, from) => {
// 对路由变化做出响应...
userData.value = await fetchUser(to.params.id)
})
</script>
七、路由拦截
正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
1、全局前置守卫
你可以使用 router.beforeEach 注册一个全局前置守卫:
const router = createRouter({ ... })
router.beforeEach((to, from) => {
// ...
// 返回 false 以取消导航
return false
})
每个守卫方法接收两个参数:
- to: 即将要进入的目标 用一种标准化的方式
- from: 当前导航正要离开的路由 用一种标准化的方式
可以返回的值如下:
- false: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
- 一个路由地址: 通过一个路由地址重定向到一个不同的地址,如同调用 router.push(),且可以传入诸如 replace: true 或 name: ‘home’ 之类的选项。它会中断当前的导航,同时用相同的 from 创建一个新导航。
// GOOD
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
2、全局后置钩子
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {
sendToAnalytics(to.fullPath)
})
- 它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
3、组件内的守卫(路由生命周期)
你可以为路由组件添加以下配置:
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
<script>
export default {
beforeRouteEnter(to, from) {
// 在渲染该组件的对应路由被验证前调用
// 不能获取组件实例 `this` !
// 因为当守卫执行时,组件实例还没被创建!
},
beforeRouteUpdate(to, from) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
},
beforeRouteLeave(to, from) {
// 在导航离开渲染该组件的对应路由时调用
// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
},
}
</script>
- 这个 离开守卫 通常用来预防用户在还未保存修改前突然离开。该导航可以通过返回 false 来取消。
beforeRouteLeave (to, from) {
const answer = window.confirm('数据未保存,你确定要离开吗!')
if (!answer) return false
}
八、路由懒加载
Vue Router 支持开箱即用的动态导入,这意味着你可以用动态导入代替静态导入:
改成箭头函数的写法就可以了
// 将
// import UserDetails from './views/UserDetails.vue'
// 替换成
const UserDetails = () => import('./views/UserDetails.vue')
const router = createRouter({
// ...
routes: [
{ path: '/users/:id', component: UserDetails }
// 或在路由定义里直接使用它
{ path: '/users/:id', component: () => import('./views/UserDetails.vue') },
],
})