1x2 VueRouter - 基础 - 动态路由与静态路由

发布于 2022年 01月 21日 06:44

VueRouter 基础教程系列 🎉

简介

  • Vue Router 使用自己的路径匹配语法,支持多种高级匹配模式,其灵感来源于 express
  • “静态路由”只支持基于地址的全匹配;“动态路由”除了可以兼容全匹配外还支持多种 “高级匹配模式”。

路径参数

“动态路由”的路径地址中含有 路径参数,使得它可以按照给定的匹配模式将符合条件的一个或多个地址映射到同一个组件上。

与动态路由建立映射关系的组件,可以理解为组件模板(它可以被符合匹配模式的多个路径命中,不像是静态路由属于一对一的关系)。

在现实场景,例如基于不同用户 ID 的用户信息会在同一个用户组件中进行渲染展示。 /user/100 以及 /user/101 等,不可能为不同的 ID 定义多个路由地址。

那么,具有路径参数的动态路由地址到底是什么样子的呢?下面来看一个简单的示例:

{path:'/users/:id', component:{name:"Users", template:'<p>{{$route.params.id}}</p>'}}

// */users/1001 -> this.$route.params.id -> 1001

归纳下路径参数的格式:用 :[pathParam] 表示,其中 pathParam 是路径参数名称,它会作为匹配内容的 key,最终以键值对的形式保存到 $route.params 中。

路径参数与正则表达式

路径参数 支持使用“正则表达式”,以获得更强大的匹配能力。使用方式是在“路径参数”后面的括符中写入具体的正则表达式:

{
    path:'/user-:userName(.*)', component:{name:'Users', template:'<h1>{{$route.params.userName}}</h1>'}
}

// */user-John -> this.$route.params.userName -> John.
{
    path:'/user-:userName(.*)/:userId', component:{name:'Users', template:'<h1>{{$route.params.userName}} | {{$route.params.userId}}</h1>'}
}

// */user-Alice/123 -> this.$route.params.userName -> Alice | 123

此时,我们可以将 /user-:userName(.*) 看做为 /user-(.*) 并将匹配分组中的内容保存到 userName 中,最终就可以使用 $route.params.userName 来访问匹配分组的值。

现在让我们再回到普通的 “路径参数”,例如 /:id ,实际上其内部也是基于正则实现的,比如 /:id 转换为正则表达式就是 ([^/]+) (匹配至少一个不以 / 结尾的字符),然后再从默认的正则匹配分组中取得 id 值保存到 $route.param.id 中。

注意转义符号

确保转义反斜杠( \ ),就像我们对 \d (变成 \\d) 所做的那样,在 JavaScript 中实际传递字符串中的反斜杠字符。

路径参数与通配符

路径参数还可以与一些常见的通配符?+* 结合使用,用来控制路径段匹配的重复次数。

关于路径段的定义,为了更好的理解,我将 path 中以 / 进行分割的每个部分定义为路径段。

通配符说明
?可以重复 0 次或 1 次
*可以重复 0 次或 n 次
+可以重复 1 次或 n 次

VueRouter 会将重复匹配的路径片段保存到一个数组中。

{
    path:'/user-:userInfo(.*)*', component:{name:'UserInfo', template:'<h1>{{$route.params.userInfo[1]}} | {{$route.params.userInfo[2]}}</h1>'}
}

// */user-Alice/1001 -> this.$route.params.userInfo -> ['Alice', '1001']

由于 ? 通配符代表了 0 个或多个,所有在实际使用中,它与普通的路径参数匹配没有什么区别,参数可能为 0 ,所以也不会保存为一个数组。

404 路由配置

当然,路径的通配符更常用于捕获所有路由或 404 - NotFound 场景。

 {path:'/:notFound(.*)*', component:{name:'404',template:'Not Found Page'}}

动态路由与组件更新

在动态路由中一个组件往往会关联着多个符合匹配模式的路径。Vue 为了复用组件实例减少性能开销,当下一个路由命中了已经被创建的组件实例时,这个组件实例就会被重用。

复用组件实例所带来的的最直观的问题,就是组件的一次性生命周期钩子不会再被触发,例如 createdmounted 等。

有两种方式可以帮助我们在一个被复用的组件实例中监听路由变化,从而执行相应的逻辑:

  • 使用 $watch 监听 $route 对象。
  • 使用路由的 beforeRouteUpdate 钩子。
{
    created(){
        this.$watch(()=>this.$route.params),
        (newData, oldData)=>{
            //执行相应的操作。
        }
    },
    beforeRouteUpdate(to, from){
        //执行相应的操作。
    }
}

注意

动态路由一定要确保路由地址被成功匹配。只有命中的地址后才会被正则分组捕获,然后将匹配的值保存到 $route.params 中。

观察下面的匹配情况:

{
    path:'/user/:id(\\d+)*' 
}

// '/user/123' ✔️,分组中的值 ['123']
// '/user/123/456' ✔️, 分组中的值 ['123', '456']
// '/user/123/abc' ×, 
// ’/user/abc/efg‘ ×

推荐文章