继续学习vue-router的部分:
4.2.10 不同的历史模式
在创建路由实例时,history配置允许我们在不同的历史模式中进行选择。
4.2.10.1 Hash模式
hash模式使用createWebHashHistory()创建的:之前用的一直是这个模式
const router = createRouter({
history:createWebHashHistory(),
routes:[...]
})
它在内部传递的实际URL之前使用了一个哈希字符(#)。由于这部分URL从未被发送到服务器,所以它不需要再服务器层面上进行任何特殊处理。不过,它在SEO中雀食有不好的影响。 如果你担心这个问题,可以使用HTML5模式。
4.2.10.2 HTML5模式
用createWebHistory()创建HTML5模式,推荐使用这个模式:
const router = createRouter({
history:createWebHistory(),
routes:[...]
})
HTML5模式下,我们的网络地址栏里面就不会与#了。但以后如果要部署到第三方的服务器上,需要做一些额外的配置。
4.2.11 导航守卫
正如起名,vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有多种方式植入路由导航中:全局的、单个路由独享的,或是 组件级的。
4.2.11.1 全局前置守卫
可以用router.beforeEach注册一个全局前置守卫:
//router.js文件中 全局路由守卫
router.beforeEach((to,from,next)=>{
console.log({to,from})
//这里可以做 用户信息的加载,对登录的判断等等 例:router.push({name:'login'})
//返回false以取消导航 return false
//这里的第三个参数next是 放行的意思,跟 return true 是一样的
//但新版本可以不用next 但要记得有这么个东西,老版本就需要next
next()
})
4.2.11.2 路由独享的守卫
我们可以直接在路由配置上定义beforeEnter守卫:
const routers = [
{
path:'/user/:id',
component: User,
beforeEnter:(to,from)=>{
return false
}
}
]
beforeEnter: 只在进入路由时触发。
4.2.11.3 组件内的守卫
- beforeRouterEnter
- beforeRouterUpdate
- beforeRouterLeave
<!-- 是写在组件内部的 useCom.vue -->
<script>
beforeRouterEnter(to,from){
//在 渲染该组件的对应路由被验证前 调用
// 不能 获取组件实例'this'!!!
//因为当守卫执行时,组件实例还没有被创建!
},
beforeRouterUpdate(to,from){
//在 当前路由改变,但是该组件被 复用 时调用
//在之前学习“响应路由参数变化”的时候也提到了这个 例如由 /user/1 跳转到 /user/2是同个组件,则会复用
//因为这种情况发生的时候,组件已经挂在好了,导航守卫可以访问组件实例'this'
},
beforeRouterLeave(to,from){
//在 导航离开渲染该组件的对应路由 时调用
//可以访问组件实例'this'
}
</script>
4.2.12 路由元信息
在定义路由的时候,定义一个meta字段:
const routes = [
{
path:'/posts',
component: Post,
//随意传参
meta:{requiresAuth:true}
}
]
//可以在路由守卫中进行一些判断
router.beforeEach((to,from)=>{
if(to.meta.requiresAuth){
//做一个简单的小判断,实际项目需要与后台互动
return false
}
return true
})
4.2.13 动态路由
我们可以把以前的路由简单地理解为静态路由:把路由定义为数组,然后把它添加到router里面去
const routes = [
{path:'/',component:Home},
......
]
那么动态路由就是将来我们在代码的执行过程当中,可以通过请求后端来实现对路由的增删改查。
4.2.13.1 添加路由
//比如拿到全局router实例,才能操作
//演示在 /about 上添加一个路由
router.addRoute({path:'/about',component:About})
//如果该路径原本有组件,需要替换
//我们也可以使用this.$route 或 route = useRoute() (在setup中)
router.replace(router.currentRoute.value.fullPath)
记住,如果需要等待新的路由显示,可与使用await router.replace()
4.2.13.2 在导航守卫中添加路由
如果决定在导航守卫内部添加或删除路由,不应该调用router.replace(),而是通过返回新的位置来触发重定向:
router.beforeEach(to => {
if(!hasNecessaryRoute(to)){
router.addRoute(generateRoute(to))
//触发重定向
return to.fullPath
}
})
4.2.13.3 删除路由
有几个不同的方法来删除现有的路由:
1.通过添加一个名称冲突的路由。如果添加与现有途径名name相同的途径,会先删除路由,再添加路由:
router.addRoute({path:'/about',name:'about',component:About})
//名字必须是唯一的
router.addRoute({path:'/other',name:'about',component:Other})
2.通过调用router.addRoute()返回的回调:
const removeRoute = router.addRoute(routeRecord)
removeRoute() //删除路由 如果存在的话
当路由没有名称时,这很有用。
3.通过使用router.removeRoute()按名称删除路由:
router.addRoute({path:'/about',name:'about',component: About})
router.removeRoute('about')
当路由被删除时,所有的别名和子路由都会被同时删除。
4.2.13.4 添加嵌套路由
依然是使用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}]
})
4.2.13.5 查看所有路由
Vue Router提供了两个功能来查看现有的路由:
router.hasRoute():检查路由是否存在router.getRoutes():获取一个包含所有路由记录的数组
拓展讲一下,例如我们想从后端请求来数据,动态地添加到router中,我们会发现route是这样定义{path:'/path',component: Com},是需要传组件的呀,那后端又传不过来组件,怎么办呢,莫慌,组件不止可以在最上方import引入,也可以在这里面用函数引入:
//原本这么写,好处是有Home可以复用
import Home from '@/components/homeCom.vue' // @代表src目录 在jsconfig.json中配置
const routes = [
{
path:'/',
component: Home
}
]
//也可以这么写,如果是后端请求来的数据可以这样写
const routes = [
{
path:'/',
component: () => import('@/components/homeCom.vue')
}
]