路由模式
Hash 模式
hash 模式是用 createWebHashHistory() 创建的:import { createRouter, createWebHashHistory } from 'vue-router' const router = createRouter({ history: createWebHashHistory(), routes: [ //... ], })
它在内部传递的实际 URL 之前使用了一个哈希字符(#)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在 SEO 中确实有不好的影响。如果你担心这个问题,可以使用 history 模式。
history 模式
用 createWebHistory() 创建 HTML5 模式,推荐使用这个模式:import { createRouter, createWebHistory } from 'vue-router' const router = createRouter({ history: createWebHistory(), routes: [ //... ], })
当使用这种历史模式时,URL 会看起来很 "正常"
不过,问题来了。由于我们的应用是一个单页的客户端应用,如果没有适当的服务器配置,用户在浏览器中直接访问,就会得到一个 404 错误。这就丑了。
不用担心:要解决这个问题,你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 index.html 相同的页面。漂亮依旧!
路由的匹配语法
大多数应用都会使用 /about 这样的静态路由和 /users/:userId 这样的动态路由,就像我们刚才在动态路由匹配中看到的那样,但是 Vue Router 可以提供更多的方式!
在参数中自定义正则
当定义像 :userId 这样的参数时,我们内部使用以下的正则 (1+) (至少有一个字符不是斜杠 / )来从 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+)*' }, ]
- / ↩