vue3+typescript【8】

路由

url的hash

  • URL的hash也就是锚点(#), 本质上是改变window.location的href属性;
  • 我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新

hash的优势就是兼容性更好,在老版IE中都可以运行,但是缺陷是有一个#,显得不像一个真实的路径。

HTML5的History

history接口是HTML5新增的, 它有六种模式改变URL而不刷新页面:

  • replaceState:替换原来的路径;
  • pushState:使用新的路径;
  • popState:路径的回退;
  • go:向前或向后改变路径;
  • forward:向前改变路径;
  • back:向后改变路径

vue-router

使用vue-router的步骤:

  • 第一步:创建路由组件的组件;
  • 第二步:配置路由映射: 组件和路径映射关系的routes数组;
  • 第三步:通过createRouter创建路由对象,并且传入routeshistory模式;
  • 第四步:使用路由: 通过<router-link><router-view>
import {createRouter, createWebHashHistory} from 'vue-router'
const routes = [
    {path:'/',redirect:'/home'}
    {path:'/home',component:()=> import('../pages/Home.vue')},
    {path:'/about',component:()=> import('../pages/About.vue')},
]
const router = createRouter({
    routes,
    history: createWebHashHistory()
})
export default router

路由懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载:
如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效;也可以提高首屏的渲染效率
component:()=> import('../pages/Home.vue')

router-link

router-link事实上有很多属性可以配置:

  • to属性:
    • 是一个字符串,或者是一个对象
  • replace属性:
    • 设置 replace 属性的话,当点击时,会调用 router.replace(),而不是 router.push()
      * active-class属性:
    • 设置激活a元素后应用的class,默认是router-link-active
  • exact-active-class属性:
    • 链接精准激活时,应用于渲染的 <a> 的 class,默认是router-link-exact-active;

动态路由基本匹配

需要将给定匹配模式的路由映射到同一个组件
在路径中使用一个动态字段来实现,我们称之为 路径参数

{
    path:'/user/:id',
    component:()=> import('../pages/User.vue')
}

获取动态路由的值

那么在上面动态路由中(User)如何获取到对应的值呢?

  • 在template中,直接通过 $route.params获取值;
    <template>
        <div>{{ $route.params.id }}</div>
    </template>
    
    • 在created中,通过 this.$route.params获取值;
      created(){
          console.log(this.$route.params.id);
      }
      
    • 在setup中,我们要使用 vue-router库给我们提供的一个hook useRoute;
      • 该Hook会返回一个Route对象,对象中保存着当前路由相关的值
      setup(){
          const route = useRoute();
          console.log(route);
          console.log(route.params.id);
      }
      

对于没有匹配到的路由,我们通常会匹配到固定的某个页面
比如NotFound的错误页面中,这个时候我们可编写一个动态路由用于匹配所有的页面

{
    path:'/:pathMatch(.*)',
    component: ()=> import('../pages/NotFound.vue')
}

同时我们可以通过 $route.params.pathMatch获取到传入的参数:
<h2>Not Found:{{$route.params.pathMatch}}</h2>
此时输出 Not Found:user/hahah/123

匹配规则加*
path:'/:pathMatch(.*)*'
此时输出 Not Found:["user","hahah","123"]

router-view

实现路由的嵌套,使用 router-view 来占位之后需要渲染的组件

//嵌套配置
{
    path:'/home',
    component:()=> import('../pages/Home.vue'),
    children:[
        {
            path:'',
            redirect:'/home/product'
        },
    ]
}

代码的页面跳转

jumpToProfile(){
    //this.$route.push('/profile')
    this.$route.push({
        path:'/profile',
        query:{name:'hahah', age:18}
    })
}

其中的参数通过KaTeX parse error: Expected '}', got 'EOF' at end of input: … `<h2>query: {{route.query.name}}`

在setup中,可以通过 useRouter 来实现页面跳转

const router = useRouter()
const jumpToProfile = ()=>{
    router.replace('./profile')
    //此时是替换当前位置,上一个页面不可回退,而push是压入一个新的页面
}

路由中的作用域插槽

router-link的v-slot

<router-link to="/about" v-slot="props" custom>
    <p>href:{{props.href}}</p>
    <p @click="navigate">跳转</p>
</router-link>
  • v-slot的props也可以解构—>v-slot="{href, route, ...}"
  • 使用custom表示我们整个元素要自定义,如果不写,那么自定义的内容会被包裹在一个 a 元素中;
  • 使用v-slot来作用域插槽来获取内部传给我们的值:
    • href:解析后的 URL;
    • route:解析后的规范化的route对象;
    • navigate:触发导航的函数;
    • isActive:是否匹配的状态;
    • isExactActive:是否是精准匹配的状态

router-view的v-slot

<router-view v-slot="props">
    <transition name="haha">
        <keep-alive>
            <component :is="props.component"></component>
        </keep-alive>
    </transition>
</router-view>
  • component为要渲染的组件
  • 此时的props也可解构---->v-slot="{component}"

动态路由

动态添加路由

使用方法 addRoute
顶级路由配置:

const categoryRoute = {
    path:'/category',
    component:()=>import('../pages/Category.vue')
}
router.addRoute(categoryRoute)

子路由配置:

const homeMomentRoute = {
    path:'moment',
    component: ()=>import(''../pages/homeMoment.vue')
}
router.addRoute('home', homeMomentRoute)

动态删除路由

  • 方式一:添加一个name相同的路由;
route.addRoute({path:'/about', name:'about', component:About})
route.addRoute({path:'/other', name:'about', component:Home})

相当于替换之前已添加的路由,两者具有相同的名字并且是唯一的

  • 方式二:通过removeRoute方法,传入路由的名称;
route.addRoute({path:'/about', name:'about', component:About})
router.removeRoute('about')
  • 方式三:通过addRoute方法的返回值回调
const removeRoute = router.addRoute(routeRecord)
removeRoute()

此时会删除路由如果该路由存在

路由其他方法:

  • router.hasRoute():检查路由是否存在。
  • router.getRoutes():获取一个包含所有路由记录的数组

路由导航守卫

vue-router 提供的导航守卫主要用来通过跳转取消的方式守卫导航
全局的前置守卫beforeEach是在导航触发时会被回调的:

  • 它有两个参数:
    • to:即将进入的路由Route对象;
    • from:即将离开的路由Route对象;
  • 它有返回值:
    • false:取消当前导航;
    • 不返回或者undefined:进行默认导航;
    • 返回一个路由地址:
    • 可以是一个string类型的路径;
    • 可以是一个对象,对象中包含path、query、params等信息;
  • 可选的第三个参数:next
    • 在Vue2中我们是通过next函数来决定如何进行跳转的;
    • 但是在Vue3中我们是通过返回值来控制的,不再推荐使用next函数,这是因为开发中很容易调用多次next
router.beforeEach((to,from)=>{
    console.log(to);
    console.log(from);
    return false;
})

可以用来实现登录守卫功能—每次跳转都会判断是否是去登录页面,如果不是的话是否本地存储了token密钥,如果没有则跳转登录

完整的导航解析流程

  1. 导航被触发

  2. 在失活的组件里调用 beforeRouteLeaves 守卫

  3. 调用全局的 beforeEach 守卫

  4. 在重用的组件里调用 beforeRouteUpdate 守卫

  5. 在路由配置里调用 beforeEnter

  6. 解析异步路由组件

  7. 在被激活的组件里调用 beforeRouteEnter

  8. 调用全局的beforeResolve 守卫

  9. 导航被确认

  10. 调用全局的 afterEach 钩子

  11. 触发 DOM 更新

  12. 调用 beforeRouteEnter 守卫中传给next的回调函数,创建好的组件实例会作为回调函数的参数传入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值