入门

用 Vue + Vue Router 创立单页利用非常简单:通过 Vue.js,曾经用组件组成了利用。当退出 Vue Router 时,将组件映射到路由上,让 Vue Router 晓得在哪里渲染它们。

HTML

<script src="https://unpkg.com/vue@3"></script><script src="https://unpkg.com/vue-router@4"></script><div id="app">  <h1>Hello App!</h1>  <p>     <router-link to="/">Go to Home</router-link>     <router-link to="/about">Go to About</router-link>  </p>  <router-view></router-view></div>

router-link

在这里没有应用惯例的 a 标签,而是应用一个自定义组件 router-link 来创立链接。这使得 Vue Router 能够在不从新加载页面的状况下更改 URL,解决 URL 的生成以及编码。

router-view

router-view 显示与 url 对应的组件。能够把它放在任何中央,以适应你的布局。

JavaScript

const Home = { template: '<div>Home</div>' }const About = { template: '<div>About</div>' }const routes = [  { path: '/', component: Home },  { path: '/about', component: About },]const router = VueRouter.createRouter({  history: VueRouter.createWebHashHistory(),  routes, // `routes: routes` 的缩写})const app = Vue.createApp({})app.use(router)app.mount('#app')

通过调用 app.use(router),能够在任意组件中以 this.$router 的模式拜访它,并且以 this.$route 的模式拜访以后路由:

带参数的动静路由匹配

很多时候,须要将给定匹配模式的路由映射到同一个组件。在 Vue Router 中,能够在门路中应用一个动静字段来实现,称之为 门路参数 :

const User = {  template: '<div>User</div>',}// 这些都会传递给 `createRouter`const routes = [  // 动静字段以冒号开始  { path: '/users/:id', component: User },]

当初像 /users/johnny 和 /users/jolyne 这样的 URL 都会映射到同一个路由。门路参数 用冒号 : 示意。

响应路由参数的变动

应用带有参数的路由时须要留神,当你从 /users/johnny 导航到/users/jolyne 时,雷同的组件实例将被重复使用。因为两个路由都渲染同个组件,比起销毁再建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会被调用。

要对同一个组件中参数的变动做出响应的话,能够简略地 watch $route 对象上的任意属性,在这个场景中,就是 $route.params :

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

路由的匹配语法

大多数利用都会应用 /about 这样的动态路由和 /users/:userId 这样的动静路由,就像方才在动静路由匹配中看到的那样,然而 Vue Router 能够提供更多的形式!

在参数中自定义正则

当定义像 :userId 这样的参数时,外部应用以下的正则 (如[ ^ / ]+) (至多有一个字符不是 / )来从 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' },]

当初,转到 /25 将匹配 /:orderId,其余状况将会匹配 /:productName。routes 数组的程序并不重要!

可反复的参数

如果须要匹配具备多个局部的路由,如 /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*' },]

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

可选参数

能够通过应用 ? 修饰符(0 个或 1 个)将一个参数标记为可选

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

这里须要留神,* 在技术上也标记着一个参数是可选的,但 ? 参数不能反复。

调试

如果要探索路由是如何转化为正则的,以理解为什么一个路由没有被匹配,或者,报告一个 bug,能够应用门路排名工具。它反对通过 URL 分享路由。

嵌套路由

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

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

通过 Vue Router,能够应用嵌套路由配置来表白这种关系。

<div id="app">  <router-view></router-view></div>const User = {  template: '<div>User {{ $route.params.id }}</div>',}// 这些都会传递给 `createRouter`const routes = [{ path: '/user/:id', component: User }]

这里的 <router-view> 是一个顶层的 router-view。它渲染顶层路由匹配的组件。同样地,一个被渲染的组件也能够蕴含本人嵌套的 <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',    component: User,    children: [      {        // 当 /user/:id/profile 匹配胜利        // UserProfile 将被渲染到 User 的 <router-view> 外部        path: 'profile',        component: UserProfile,      },      {        // 当 /user/:id/posts 匹配胜利        // UserPosts 将被渲染到 User 的 <router-view> 外部        path: 'posts',        component: UserPosts,      },    ],  },]

须要留神,以 / 结尾的嵌套门路将被视为根门路。这容许利用组件嵌套,而不用应用嵌套的 URL。

如你所见,children 配置只是另一个路由数组,就像 routes 自身一样。因而,你能够依据本人的须要,一直地嵌套视图。

编程式导航

除了应用 <router-link> 创立 a 标签来定义导航链接,还能够借助 router 的实例办法,通过编写代码来实现。

导航到不同的地位

想要导航到不同的 URL,能够应用 router.push 办法。这个办法会向 history 栈增加一个新的记录,所以,当用户点击浏览器后退按钮时,会回到之前的 URL。

当点击 <router-link> 时,外部会调用这个办法,所以点击 <router-link :to="..."> 相当于调用 router.push(...) :

该办法的参数能够是一个字符串门路,或者一个形容地址的对象。

// 字符串门路router.push('/users/eduardo')// 带有门路的对象router.push({ path: '/users/eduardo' })// 命名的路由,并加上参数,让路由建设 urlrouter.push({ name: 'user', params: { username: 'eduardo' } })// 带查问参数,后果是 /register?plan=privaterouter.push({ path: '/register', query: { plan: 'private' } })// 带 hash,后果是 /about#teamrouter.push({ path: '/about', hash: '#team' })

如果提供了 path,params 会被疏忽,上述的 query 并不属于这种状况。取而代之的是上面的做法,须要提供路由的 name 或手写残缺的带有参数的 path :

const username = 'eduardo'// 能够手动建设 url,但必须本人解决编码router.push(`/user/${username}`) // -> /user/eduardo// 同样router.push({ path: `/user/${username}` }) // -> /user/eduardo// 如果可能的话,应用 `name` 和 `params` 从主动 URL 编码中获益router.push({ name: 'user', params: { username } }) // -> /user/eduardo// `params` 不能与 `path` 一起应用router.push({ path: '/user', params: { username } }) // -> /user

因为属性 to 与 router.push 承受的对象品种雷同,所以两者的规定完全相同。

router.push 和所有其余导航办法都会返回一个 Promise,让咱们能够等到导航实现后才晓得是胜利还是失败。

替换以后地位

它的作用相似于 router.push,惟一不同的是,它在导航时不会向 history 增加新记录,正如它的名字所暗示的那样——它取代了以后的条目。

也能够间接在传递给 router.push 的 routeLocation 中减少一个属性 replace: true :

router.push({ path: '/home', replace: true })// 相当于router.replace({ path: '/home' })