likes
comments
collection
share

vue-router - 动态路径参数

作者站长头像
站长
· 阅读数 36

有时候我们会有多个路由,它们的 URL 形式可能不完全相同,但是它们的功能或者需要渲染的内容是相同的,因此这些路由都需要映射到同一个组件上进行处理

在这种情况下,我们可以使用 Vue Router 的动态路由功能,将这些路由与同一个组件相关联

// 此时像/users/johnny 和 /users/jolyne 这类路由都会匹配到User这个组件
const routes = [
  // 动态字段以冒号开始 在这里动态路由参数就是:id
  // 动态路径参数 又被称之为params参数
  { path: '/users/:id', component: User },
]

动态路径参数 用冒号 : 表示

当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params 的形式暴露出来

const User = {
  template: '<div>User {{ $route.params.id }}</div>',
}

你可以在同一个路由中设置有多个 路径参数,它们会映射到 $route.params 上的相应字段

匹配模式匹配路径$route.params
/users/:username/users/eduardo{ username: 'eduardo' }
/users/:username/posts/:postId/users/eduardo/posts/123{ username: 'eduardo', postId: '123' }

除了 $route.params 之外,$route 对象还公开了其他有用的信息,如 $route.query(如果 URL 中存在参数)、$route.hash

监听路由参数的改变

在使用带有参数的路由时需要注意,如果用户从 /users/johnny 导航到 /users/jolyne,那么将会重复使用同一个组件实例

因为这两个路由都会渲染同一个组件,为了提高性能,Vue Router 会尽可能地复用组件实例而不是销毁再创建。然而,这也意味着组件的生命周期钩子不会被调用

如果需要在同一个组件中对参数的变化做出响应,可以通过在组件中使用 watch 或 computed 属性来监视 $route 对象上的参数变化

const User = {
  template: '...',
  created() {
    this.$watch(
      () => this.$route.params,
      (toParams, previousParams) => {
        // 对路由变化做出响应...
      }
    )
  },
}

或者,使用 beforeRouteUpdate 导航守卫

const User = {
  template: '...',
  async beforeRouteUpdate(to, from) {
    // 对路由变化做出响应...
    this.userData = await fetchUser(to.params.id)
  },
}

404 Not found

Vue Router 使用常规参数来匹配 URL 片段之间的字符,这些片段由斜杠(/)分隔

如果我们想要匹配任意路径,我们可以使用自定义的正则表达式来定义路径参数

即在路径参数后面的括号中,我们可以加入正则表达式,以进行高级路由匹配

const routes = [
  // 匹配以user-开头的路径
  // 如路径为 /user-abc,$route.params.afterUser的值为abc
  { path: '/user-:afterUser(.*)', component: UserGeneric },
  
  // 会匹配没有被之前路由捕获的所有路径 
  // 如路径为 /foo/bar/baz 会匹配到NotFound,$route.params.pathMatch的值为/foo/bar/baz
  { path: '/:pathMatch(.*)', name: 'NotFound', component: NotFound },
  
  // 如路径为 /foo/bar/baz 会匹配到NotFound,$route.params.pathMatch的值为 ['foo', 'bar', 'baz']
  // { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
]
this.$router.push({
  name: 'NotFound',
  // 保留当前路径并删除第一个字符,以避免目标 URL 以 `//` 开头。
  params: { pathMatch: this.$route.path.substring(1).split('/') },
  // 保留现有的查询和 hash 值,如果有的话
  query: this.$route.query,
  hash: this.$route.hash,
})

命名路由

除了 path 之外,你还可以为任何路由提供一个唯一的 name

因为name必须是唯一的,所以如果每一个路由都是命名路由的时候,路由的先后顺序就变得没有那么重要了

const routes = [
  {
    path: '/user/:username',
    name: 'user',
    component: User,
  }
]

要链接到一个命名的路由,可以向 router-link 组件的 to 属性传递一个对象:

<!-- 通过params选项传入的参数会自动编解码 -->
<router-link :to="{ name: 'user', params: { username: 'erina' }}">
  User
</router-link>

这跟代码调用 router.push() 是一回事

router.push({ name: 'user', params: { username: 'erina' } })

嵌套路由

一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构

/user/johnny/profile                     /user/johnny/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

一个被渲染的组件也可以包含自己嵌套的 <router-view>。例如,如果我们在 User 组件的模板内添加一个 <router-view>

const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `,
}

要将组件渲染到这个嵌套的 router-view 中,我们需要在路由中配置 children

const routes = [
  {
    path: '/user/:id',
    // 当/user/:id 匹配成功
    // 会渲染User组件
    component: User,
    // 注意,以 / 开头的嵌套路径将被视为根路径,这允许我们利用组件嵌套,而不必使用嵌套的 URL
    children: [
      // 当 /user/:id 匹配成功,User组件内部的router-view会被渲染为UserHome
      { path: '', component: UserHome },
      
      {
        // 当 /user/:id/profile 匹配成功,User组件内部的router-view会被渲染为UserProfile
        path: 'profile',
        component: UserProfile,
      },
      {
        // 当 /user/:id/posts 匹配成功,User组件内部的router-view会被渲染为UserPosts
        path: 'posts',
        component: UserPosts,
      },
    ],
  },
]
转载自:https://juejin.cn/post/7248109163850727481
评论
请登录