Vue Router3.x/Vue Router4.x 保姆级教程

Vue Router3

1.动态路由匹配

动态路径参数 以冒号开头

设置单个参数

// 路由配置
{ 
    path: '/user/:id',
    name:'user'
    component: User 
}

// 跳转匹配路由
this.$router.push('/user/8'); // 第一种方式
this.$router.push({ name: 'user', params: { id: 8 } }); // 第二种方式

// 获取方式
this.$route.params

// 输出结果
{id: '8'}

也可以设置多个参数

// 路由配置
{ 
    path: '/user/:id/:type',
    name:'user'
    component: User 
}

// 跳转匹配路由
this.$router.push('/user/8/one');
this.$router.push({ name: 'user', params: { id: 8,type:'one' } });

// 获取方式
this.$route.params

// 输出结果
{id: '8', type: 'one'}

2.嵌套路由

要在页面嵌套别的组件,需要配置父路由的children属性,在父页面添加 router-view 占位符

当路径为 /nestRoute/zhangsan 时候加载 zhangsan 的组件,/nestRoute/lisi 加载 lisi 组件

const router = new VueRouter({
    routes: [
        {
        path: '/nestRoute',
        component: nestRoute,
        children: [
            { 
            path: 'zhangsan',
            component: zhangsan
            },
            { 
            path: 'lisi',
            component: lisi
            }
        ]
        }
    ]
}) 

注意:以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。

3.编程式的导航

router、routes、route的区别

1、router:路由器对象(new的路由器对象),包含一些操作路由的功能函数,来实现编程式导航。一般指的是在任何组件内访问路由。如:路由编程式导航的$router.push()

2、routes:指创建vue-router路由实例的配置项。用来配置多个route路由对象

3、route:指路由对象表示当前激活的路由的状态信息。如:this.$route指的是当前路由对象,path/meta/query/params

声明式导航

router-link 会生成a标签

router-link 等同于router.push()

编程式导航

一、this.$router.replace() 它不会向 history 添加新记录,不能后退

二、this.$router.push() 这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

  • 字符串
    router.push('home')

  • 对象
    router.push({ path: 'home' })

  • 命名的路由 router里面配置的name名字 params 动态路径参数,以冒号开头 ,如果路由里面配置了/user/:userId 在地址栏显示,如果不配置不在地址栏显示,在页面也可以使用params拿到传过来的参数
    router.push({ name: 'user', params: { userId: '123' }})

  • 带查询参数,变成 /register?plan=private
    router.push({ path: 'register', query: { plan: 'private' }})

注意:如果提供了 path,params 会被忽略

const userId = '123'

router.push({ name: 'user', params: { userId }}) ====> /user/123

router.push({ path: `/user/${userId}` }) ====> /user/123

// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) ====> /user

同样的规则也适用于 router-link 组件的 to 属性。

router.go

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

// 后退一步记录,等同于 history.back()
router.go(-1)

// 前进 3 步记录
router.go(3)

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)  

操作 History

你也许注意到 router.push、 router.replace 和 router.go 跟

window.history.pushState、 window.history.replaceState 和 window.history.go (opens new window)好像,实际上它们确实是效仿 window.history API 的。

因此,如果你已经熟悉 Browser History APIs (opens new window),那么在 Vue Router 中操作 history 就是超级简单的。

还有值得提及的,Vue Router 的导航方法 (push、 replace、 go) 在各类路由模式 (history、 hash 和 abstract) 下表现一致。

4.命名路由

有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在 routes 配置中给路由设置name属性。

  const router = new VueRouter({
    routes: [
      {
        path: '/user/:userId',
        name: 'user',
        component: User
      }
    ]
  })

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

  <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

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

  router.push({ name: 'user', params: { userId: 123 } })

5.命名视图

同级展示多个视图,而不是嵌套展示。例如:企业官网header、content、footer 三个视图,这个时候命名视图就派上用场了。如果router-view 没有设置名字,那么默认为default

  <router-view class="head"></router-view>

  <router-view class="cont" name="content"></router-view>
  
  <router-view class="foot" name="footer"></router-view>

一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s):

  const router = new VueRouter({
    routes: [
      {
        path: 'website',
        components: {
          default: () => import('@/views/vue/route/nameView/header'),
          content: () => import('@/views/vue/route/nameView/content'),
          footer: () => import('@/views/vue/route/nameView/footer')
        }
      }
    ]
  })

嵌套命名视图

我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 router-view 组件。我们以一个设置面板为例:

  /settings/emails                                       /settings/profile
  +-----------------------------------+                  +------------------------------+
  | UserSettings                      |                  | UserSettings                 |
  | +-----+-------------------------+ |                  | +-----+--------------------+ |
  | | Nav | UserEmailsSubscriptions | |  +------------>  | | Nav | UserProfile        | |
  | |     +-------------------------+ |                  | |     +--------------------+ |
  | |     |                         | |                  | |     | UserProfilePreview | |
  | +-----+-------------------------+ |                  | +-----+--------------------+ |
  +-----------------------------------+                  +------------------------------+


  //嵌套命名视图
  
  <div>
    <h1>User Settings</h1>
    <NavBar/>
    <router-view/>
    <router-view name="helper"/>
  </div>

  
  {
    path: '/settings',
    // 你也可以在顶级路由就配置命名视图
    component: UserSettings,
    children: [{
      path: 'emails',
      component: UserEmailsSubscriptions
    }, {
      path: 'profile',
      components: {
        default: UserProfile,
        helper: UserProfilePreview
      }
    }]
  }

6.重定向和别名

重定向

重定向也是通过 routes 配置来完成,下面例子是从 /a 重定向到 /b:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})

  重定向的目标也可以是一个命名的路由:
  const router = new VueRouter({
    routes: [
      { path: '/a', redirect: { name: 'foo' }}
    ]
  })


  甚至是一个方法,动态返回重定向目标:
  const router = new VueRouter({
    routes: [
      { path: '/a', redirect: to => {
        // 方法接收 目标路由 作为参数
        // return 重定向的 字符串路径/路径对象
        const { hash, query, params } = to
        if(hash=='') return {name:'',hash:''}
        if(query=='') return {path:'',query:null}
        if(params=='') return {'/a/:id'}
        else return {'/a'}
      }}
    ]
  })

别名

/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。

  const router = new VueRouter({
    routes: [
      { path: '/a', component: A, alias: '/b' }
    ]
  })

  “别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。

7.通过props传参

// 路由配置
{
    path: '/routeParam/:id',
    name: 'RouteParam',
    component: () => import('@/views/vue/route/routeParam'),
    meta: { title: '路由组件传参' },
    // props: true, 布尔模式
    // props: { name: 'zhangsan'}  对象模式
    props: (route) => ({    //函数模式
        name: 'zhangsan',
        id: route.params.id,
        // hh:route.query.id
    })
},

正常传参

$router.push({ name: 'RouteParam', params: { id: 333 } })

通过 this.$route.params 获取参数

通过布尔模式传参

通过 props 解耦,在路由中设置 props:true,在页面中添加props: ['id'],在页面直接获取id就行

对于包含命名视图的路由,你必须分别为每个命名视图添加 props 选项:

路径  path: '/routeParam/:id',

$router.push('/routeParam/666')

获取直接使用 {{ id }}

对象模式

如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。

 const router = new VueRouter({
    routes: [
        {
        path: '/routeParam/:id',
        component: Promotion,
        props: { name: 'zhangsan' }
        }
    ]
})

export default {
    props: ['id', 'name'],
};

页面直接使用 {{name}} 获取参数

函数模式

你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。

const router = new VueRouter({
    routes: [
        {
            path: '/search',
            component: SearchUser,
            props: route => ({ query: route.query.q })
        }
    ]
})

获取方式 通过 {{ name }}
export default {
  props: ['id', 'name','hh'],
}

8.导航守卫

全局前置守卫

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。

router.beforeEach((to, from, next) => {
    console.log(to);
    console.log(from);
    next()
})

to: 即将要进入的目标 路由对象

from: 当前导航正要离开的路由

next: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数

全局解析守卫

在 2.5.0+ 你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

全局后置钩子

你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

router.afterEach((to, from) => {
    // ...
})

路由独享的守卫

在路由配置上直接定义 beforeEnter 守卫:

const router = new VueRouter({
    routes: [
        {
            path: '/foo',
            component: Foo,
            beforeEnter: (to, from, next) => {
                // ...
            }
        }
    ]
})

这些守卫与全局前置守卫的方法参数是一样的。

组件内的守卫

可以在组件中定义守卫,可以在路由组件内直接定义以下路由导航守卫:

  • beforeRouteEnter

  • beforeRouteUpdate (2.2 新增)

  • beforeRouteLeave

export default {
    beforeRouteEnter(to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
    },
    beforeRouteUpdate(to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
    },
    beforeRouteLeave(to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
    },
};

完整的导航解析流程

1、导航被触发。

2、在失活的组件里调用 beforeRouteLeave 守卫。

3、调用全局的 beforeEach 守卫。

4、在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。

5、在路由配置里调用 beforeEnter。

6、解析异步路由组件。

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

8、调用全局的 beforeResolve 守卫 (2.5+)。

9、导航被确认。

10、调用全局的 afterEach 钩子。

11、触发 DOM 更新。

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

9.路由元信息

定义路由的时候可以配置 meta 字段:

const router = new VueRouter({
    routes: [
        {
            path: '/foo',
            component: Foo,
            children: [
                {
                path: 'bar',
                component: Bar,
                // a meta field
                meta: { requiresAuth: true }
                }
            ]
        }
    ]
})

routes 配置中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录

例如,根据上面的路由配置,/foo/bar 这个 URL 将会匹配父路由记录以及子路由记录。

一个路由匹配到的所有路由记录会暴露为 route 对象 (还有在导航守卫中的路由对象) 的route.matched 数组。因此,我们需要遍历 $route.matched 来检查路由记录中的 meta 字段。

在全局导航守卫中检查元字段:

router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requiresAuth)) {
        if (!auth.loggedIn()) {
        next({
            path: '/login',
            query: { redirect: to.fullPath }
        })
        } else {
            next()
        }
    } else {
        next() // 确保一定要调用 next()
    }
})

10.过渡动效

单个路由的过渡

<transition name="slide-right">
    <router-view></router-view>
</transition>


// 添加样式
.slide-left-enter, .slide-right-leave-to {
    opacity: 0;
    transform: translateX(100%)
}

.slide-left-leave-to, .slide-right-enter {
    opacity: 0;
    transform: translateX(-100%)
}

.slide-left-enter-active, .slide-left-leave-active, .slide-right-enter-active, .slide-right-leave-active {
    transition: 1.5s;
    position: absolute;
    top:0;
}

11.数据获取

有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,你需要从服务器获取用户的数据。我们可以通过两种方式来实现:

1、导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。

当你使用这种方式时,我们会马上导航和渲染组件,然后在组件的 created 钩子中获取数据。这让我们有机会在数据获取期间展示一个 loading 状态,还可以在不同视图间展示不同的 loading 状态。

2、导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。从技术角度讲,两种方式都不错 —— 就看你想要的用户体验是哪种。

通过这种方式,我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter 守卫中获取数据,当数据获取成功后只调用 next 方法。

12.滚动行为

只有在全局下才可以起作用,body有滚动条才可以,

scrollBehavior(to, from, savedPosition) {
    // return 期望滚动到哪个的位置
    console.log(savedPosition);
    return {y:200}
}

13.捕获所有路由或 404 Not found 路由

匹配所有路径
{ path: '*', redirect: '/404', hidden: true }

  匹配以 `/user-` 开头的任意路径
  { path: '/user-*', redirect: '/404', hidden: true }

注意:通配符的路由应该放在最后

当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:

  给出一个路由 { path: '/user-*' }
  this.$router.push('/user-admin')
  this.$route.params.pathMatch ===> 'admin'

  给出一个路由 { path: '*' }
  this.$router.push('/non-existing')
  this.$route.params.pathMatch ===> '/non-existing'

14. 路由组件传参的方式(总结)

通过 params 传递

路由配置

const routes = [
  // 动态段以冒号开始
  { path: 'details/:id', name: "details", component: Details },
]

传参方式

// 字符串路径
this.$router.push('/details/001')

// 带有路径的对象
this.$router.push({path: '/details/001'})

// 命名路由,路由配置时,需要 name 字段
this.$router.push({ name: 'details', params: { id: '001' } })

// 注意,如果提供了 path,params 会被忽略:`params` 不能与 `path` 一起使用
router.push({ path: '/details', params: { id: '001' } }) // -> /details

获取方式

this.$route.params

通过 query 传递

这种情况下 query (查询参数)传递的参数会显示在 url 后面,如:/details/001?kind=car。

路由配置

const routes = [
  { path: 'details/:id', name: "details", component: Details },
]

传参方式

// 使用 query 时,以下三种方式都是可行的:
this.$router.push('/details/001?kind=car')

this.$router.push({ path: '/details/001', query: { kind: "car" }})

this.$router.push({ name: 'details', params: { id: '001' }, query: { kind: 'car' }})

获取方式

this.$route.query

通过 hash 传递

通过此方式,url 路径中带有 hash,例如:/details/001#car。

路由配置

const routes = [
  { path: 'details/:id', name: "details", component: Details },
]

传参方式

// 使用 hash 时,以下三种方式都是可行的(同 query):
this.$router.push('/details/001#car')

this.$router.push({ path: '/details/001', hash: '#car'})

this.$router.push({ name: 'details', params: { id: '001' }, hash: 'car'})

获取方式

$route.hash.slice(1)

通过 props 传递

在组件中使用 $route 会与路由紧密耦合,这限制了组件的灵活性,因为它只能用于特定的 URL。虽然这不一定是件坏事,但我们可以通过 props 配置来解除这种行为。

以解耦的方式使用 props 进行参数传递,主要是在路由配置中进行操作。

  1. 布尔模式
    当 props 设置为 true 时,route.params 将被设置为组件的 props。

路由配置中,增加 props 字段,并将值 设置为 true

const User = {
  props: ['id'], // 组件中通过 props 获取 id
  template: '<div>User {{ id }}</div>'
}

const routes = [{ path: '/user/:id', component: User, props: true }]

注意:对于有命名视图的路由,你必须为每个命名视图定义 props 配置:

const routes = [
  {
    path: '/user/:id',
    components: { default: User, sidebar: Sidebar },
    // 为 User 提供 props
    props: { default: true, sidebar: false }
  }
]
  1. 对象模式

当 props 是一个对象时,它将原样设置为组件 props。当 props 是静态的时候很有用。

路由配置

const routes = [
  {
    path: '/hello',
    component: Hello,
    props: { name: 'World' }
  }
]

组件中获取数据

const Hello = {
  props: {
    name: {
      type: String,
      default: 'Vue'
    }
  },
  template: '<div> Hello {{ name }}</div>'
}

<Hello /> 组件默认显示 Hello Vue,但路由配置了 props 对象,当路由跳转到 /hello 时,会显示传递过来的 name, 页面会显示为 Hello World。

  1. 函数模式

可以创建一个返回 props 的函数。这允许你将参数转换为其他类型,将静态值与基于路由的值相结合等等。

使用函数模式时,返回 props 的函数接受的参数为路由记录 route。

路由配置

// 创建一个返回 props 的函数
const dynamicPropsFn = (route) => {
  return { name: route.query.say + "!" }
}
const routes = [
  {
    path: '/hello',
    component: Hello,
    props: dynamicPropsFn
  }
]

组件获取数据

// 当 URL 为 /hello?say=World 时, 将传递 {name: 'World!'} 作为 props 传给 Hello 组件。
const Hello = {
  props: {
    name: {
      type: String,
      default: 'Vue'
    }
  },
  template: '<div> Hello {{ name }}</div>'
}

注意:请尽可能保持 props 函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义 props,请使用包装组件,这样 vue 才可以对状态变化做出反应。

通过 Vuex 进行传递

  1. store 存储状态

  2. A 组件更改 store 中的状态

  3. B 组件从 store 中获取

通过前端本地存储等方式

  1. Local Storage;

  2. Session Storage;

  3. IndexedDB;

  4. Web SQL;

  5. Cookies。

Vue Router4

1.index.js

3.x的写法
这种写法是比较通用的,配置的是动态路由,前台只配置常用的几个即可。

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [{
  path: '/',
  name: '首页',
  component: () =>
    import( /* webpackChunkName: "page" */ '@/views/index'),
  meta: {
    requireAuth: true,
  },
  children: [{
    path: '/index',
    name: '首页',
    component: () =>
      import( /* webpackChunkName: "page" */ '@/views/wel'),
    meta: {
      requireAuth: true,
    }
  }]
}]
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
export default router

4.x的写法
导入createRouter, createWebHistory这两个方法,使用createWebHistory方法创建一个routerHistory对象,使用 createRouter 创建路由器。

import { createRouter, createWebHistory } from "vue-router";
import login from "../views/login.vue";
import index from "../views/index.vue";
const routes = [
  {
    path: "/login",
    name: "登录",
    component: login,
    meta: {
      requireAuth: false,
    },
  }, {
    path: "/",
    name: "首页",
    component: index,
    meta: {
      requireAuth: true,
    },
  },
];
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
});
export default router;

2.创建方式

3.x的写法

import VueRouter from "vue-router"'
const router = new VueRouter({
    // options
    ......
})

4.x的写法

import { createRouter } from "vue-router"
const router = createRouter({
    // opyions.....
})

3.路由模式

3.x的写法

const router = new VueRouter({
    mode: 'hash' / 'history'
})

4.x的写法

import {createRouter, createWebHashHistory,createWebHashHistory} from 'vue-router'
const router = createRouter({
    history:createWebHashHistory() / createWebHashHistory()
})

4.动态路由匹配

3.x的写法

{ path: '*',component: 404page }

4.x的写法

// 将匹配所有内容并将其放在 `$route.params.pathMatch` 下
{ path:'/:pathMatch(.*)*',component: NotFound  },

// 将匹配以 `/user-` 开头的所有内容,并将其放在 `$route.params.afterUser` 下
{ path: '/user-:afterUser(.*)', component: UserGeneric  },

使用以前的*语法会报错,也无法解析到任意路径上。

5.重定向

3.x的写法

{
    path: '*',
    redirect: Home
}

4.x的写法

{
    path: '/:pathMatch(.*)*', // 需要使用正则去匹配
    redirect: Home,
}

6.挂载方式

3.x的写法

import router from './router.js'

new Vue({
    router
})

4.x的写法

import { createApp } from 'vue'import router from './router.js'
import App from './App.vue'

createApp(App).use(router).mount('#app');

7.件中的使用

3.x的写法

export default({       
    methods:{         
        linkToHome(){           
            this.$router.push({path:'/'   })
        }
    }
})

4.x的写法
因为setup中不能访 this,所以提供两个api来获取 router 和 route , useRouter() 和 useRoute()

import { useRouter,useRoute } from "vue-router"

export default({      
    setup(){
      const router = useRouter();
      const route = useRoute();
      const linkToHome = () => {
        router.push({path:'/'})
      }
      return{ linkToHome }
    }
})

8.导航守卫

由于 vue3 composition api的原因,beforeRouteUpdate 和 beforeRouteLeave被替换为 onBeforeRouteUpdate 和 onBeforeRouteLeave

9.路由的匹配语法

在参数中自定义正则

当定义像 :userId 这样的参数时,我们内部使用以下的正则 ([^/]+) (至少有一个字符不是斜杠 / )来从 URL 中提取参数。这很好用,除非你需要根据参数的内容来区分两个路由。想象一下,两个路由 /:orderId 和 /:productName,两者会匹配完全相同的 URL,所以我们需要一种方法来区分它们。最简单的方法就是在路径中添加一个静态部分来区分它们:

const routes = [
  // 匹配 /o/3549
  { path: '/o/:orderId' },
  // 匹配 /p/books
  { path: '/p/:productName' },
]

但在某些情况下,我们并不想添加静态的 /o /p 部分。由于,orderId 总是一个数字,而 productName 可以是任何东西,所以我们可以在括号中为参数指定一个自定义的正则:

const routes = [
  // /:orderId -> 仅匹配数字
  { path: '/:orderId(\\d+)' },
  // /:productName -> 匹配其他任何内容
  { path: '/:productName' },
]

可重复的参数

如果你需要匹配具有多个部分的路由,如 /first/second/third,你应该用 *(0 个或多个)和 +(1 个或多个)将参数标记为可重复:

const routes = [
  // /:chapters ->  匹配 /one, /one/two, /one/two/three, 等
  { path: '/:chapters+' },

  // /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等
  { path: '/:chapters*' },
]

这将为你提供一个参数数组,而不是一个字符串,并且在使用命名路由时也需要你传递一个数组:

// 给定 { path: '/:chapters*', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 产生 /
router.resolve({ name: 'chapters', params: { chapters: ['a', 'b'] } }).href
// 产生 /a/b

// 给定 { path: '/:chapters+', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// 抛出错误,因为 `chapters` 为空 

这些也可以通过在右括号后添加它们与自定义正则结合使用:

const routes = [
  // 仅匹配数字
  // 匹配 /1, /1/2, 等
  { path: '/:chapters(\\d+)+' },
  // 匹配 /, /1, /1/2, 等
  { path: '/:chapters(\\d+)*' },
]

Sensitive 与 strict 路由配置

默认情况下,所有路由是不区分大小写的,并且能匹配带有或不带有尾部斜线的路由。例如,路由 /users 将匹配 /users、/users/、甚至 /Users/。这种行为可以通过 strict 和 sensitive 选项来修改,它们可以既可以应用在整个全局路由上,又可以应用于当前路由上:

const router = createRouter({
  history: createWebHistory(),
  routes: [
    // 将匹配 /users/posva 而非:
    // - /users/posva/ 当 strict: true
    // - /Users/posva 当 sensitive: true
    { path: '/users/:id', sensitive: true },
    // 将匹配 /users, /Users, 以及 /users/42 而非 /users/ 或 /users/42/
    { path: '/users/:id?' },
  ]
  strict: true, // applies to all routes
})

可选参数

你也可以通过使用 ? 修饰符(0 个或 1 个)将一个参数标记为可选:

const routes = [
  // 匹配 /users 和 /users/posva
  { path: '/users/:userId?' },
  // 匹配 /users 和 /users/42
  { path: '/users/:userId(\\d+)?' },
]

请注意,* 在技术上也标志着一个参数是可选的,但 ? 参数不能重复。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容