从0学习Vue3(10)

176 阅读4分钟

继续学习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')
     }
 ]