很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 组件,它应该对所有用户进行渲染,但用户 ID 不同。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数 :
现在像 和 这样的 URL 都会映射到同一个路由。
路径参数 用冒号 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 的形式暴露出来。因此,我们可以通过更新 的模板来呈现当前的用户 ID:
你可以在同一个路由中设置有多个 路径参数,它们会映射到 上的相应字段。例如:
除了 之外, 对象还公开了其他有用的信息,如 (如果 URL 中存在参数)、 等。你可以在 API 参考中查看完整的细节。
这个例子的 demo 可以在这里找到。
使用带有参数的路由时需要注意的是,当用户从 导航到 时,相同的组件实例将被重复使用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会被调用。
要对同一个组件中参数的变化做出响应的话,你可以简单地 watch 对象上的任意属性,在这个场景中,就是 :
或者,使用 导航守卫,它还允许你取消导航:
常规参数只匹配 url 片段之间的字符,用 分隔。如果我们想匹配任意路径,我们可以使用自定义的 路径参数 正则表达式,在 路径参数 后面的括号中加入 正则表达式 :
在这个特定的场景中,我们在括号之间使用了自定义正则表达式,并将 参数标记为可选可重复。这样做是为了让我们在需要的时候,可以通过将 拆分成一个数组,直接导航到路由:
更多内容请参见重复参数部分。
如果你正在使用历史模式,请务必按照说明正确配置你的服务器。
Vue Router 使用自己的路径匹配语法,其灵感来自于 ,因此它支持许多高级匹配模式,如可选的参数,零或多个 / 一个或多个,甚至自定义的正则匹配规则。请查看高级匹配文档来探索它们。
大多数应用都会使用 这样的静态路由和 这样的动态路由,就像我们刚才在动态路由匹配中看到的那样,但是 Vue Router 可以提供更多的方式!
当定义像 这样的参数时,我们内部使用以下的正则 (至少一个不是斜杠 的字符)来从 URL 中提取参数。这很好用,除非你需要根据参数的内容来区分两个路由。想象一下,两个路由 和 ,两者会匹配完全相同的 URL,所以我们需要一种方法来区分它们。最简单的方法就是在路径中添加一个静态部分来区分它们:
但在某些情况下,我们并不想添加静态的 部分。由于, 总是一个数字,而 可以是任何东西,所以我们可以在括号中为参数指定一个自定义的正则:
现在,转到 将匹配 ,其他情况将会匹配 。 数组的顺序并不重要!
如果你需要匹配具有多个部分的路由,如 ,你应该用 (0 个或多个)和 (1 个或多个)将参数标记为可重复:
这将为你提供一个参数数组,而不是一个字符串,并且在使用命名路由时也需要你传递一个数组:
这些也可以通过在右括号后添加它们与自定义正则结合使用:
默认情况下,所有路由是不区分大小写的,并且能匹配带有或不带有尾部斜线的路由。例如,路由 将匹配 、、甚至 。这种行为可以通过 和 选项来修改,它们既可以应用在整个全局路由上,又可以应用于当前路由上:
你也可以通过使用 修饰符(0 个或 1 个)将一个参数标记为可选:
请注意, 在技术上也标志着一个参数是可选的,但 参数不能重复。
如果你需要探究你的路由是如何转化为正则的,以了解为什么一个路由没有被匹配,或者,报告一个 bug,你可以使用路径排名工具。它支持通过 URL 分享你的路由。
一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,例如:
通过 Vue Router,你可以使用嵌套路由配置来表达这种关系。
接着上节创建的 app :
这里的 是一个顶层的 。它渲染顶层路由匹配的组件。同样地,一个被渲染的组件也可以包含自己嵌套的 。例如,如果我们在 组件的模板内添加一个 :
要将组件渲染到这个嵌套的 中,我们需要在路由中配置 :
注意,以 开头的嵌套路径将被视为根路径。这允许你利用组件嵌套,而不必使用嵌套的 URL。
如你所见, 配置只是另一个路由数组,就像 本身一样。因此,你可以根据自己的需要,不断地嵌套视图。
此时,按照上面的配置,当你访问 时,在 的 里面什么都不会呈现,因为没有匹配到嵌套路由。也许你确实想在那里渲染一些东西。在这种情况下,你可以提供一个空的嵌套路径:
这个例子的 demo 可以在这里找到。
在处理命名路由时,你通常会给子路由命名:
这将确保导航到 时始终显示嵌套路由。
在一些场景中,你可能希望导航到命名路由而不导航到嵌套路由。例如,你想导航 而不显示嵌套路由。那样的话,你还可以命名父路由,但请注意重新加载页面将始终显示嵌套的子路由,因为它被视为指向路径 的导航,而不是命名路由:
We can also take advantage of the parent-child relationship between routes without needing to nest route components. This can be useful for grouping together routes with a common path prefix, or when working with more advanced features, such as per-route navigation guards or route meta fields.
To achieve this, we omit the and options from the parent route:
As the parent doesn't specify a route component, the top-level will skip over the parent and just use the component from the relevant child instead.
当创建一个路由时,我们可以选择给路由一个 :
然后我们可以使用 而不是 来传递 属性给 :
上述示例将创建一个指向 的链接。
- 在演练场上查看。
使用 有很多优点:
- 没有硬编码的 URL。
- 的自动编码/解码。
- 防止你在 URL 中出现打字错误。
- 绕过路径排序,例如展示一个匹配相同路径但排序较低的路由。
所有路由的命名都必须是唯一的。如果为多条路由添加相同的命名,路由器只会保留最后那一条。你可以在动态路由章节了解更多。
Vue Router 有很多其他部分可以传入网址,例如 和 方法。我们将在编程式导航指南中详细介绍这些方法。就像 属性一样,这些方法也支持通过 传入网址:
除了使用 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。
注意: 下面的示例中的 指代路由器实例。在组件内部,你可以使用 属性访问路由,例如 。如果使用组合式 API,你可以通过调用 来访问路由器。
想要导航到不同的 URL,可以使用 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,会回到之前的 URL。
当你点击 时,内部会调用这个方法,所以点击 相当于调用 :
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:
注意:如果提供了 , 会被忽略,上述例子中的 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 或手写完整的带有参数的 :
当指定 时,可提供 或 参数(或者对于可重复的参数可提供一个数组)。任何其他类型(如对象、布尔等)都将被自动字符串化。对于可选参数,你可以提供一个空字符串()或 来移除它。
由于属性 与 接受的对象种类相同,所以两者的规则完全相同。
和所有其他导航方法都会返回一个 Promise,让我们可以等到导航完成后才知道是成功还是失败。我们将在 Navigation Handling 中详细介绍。
它的作用类似于 ,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。
也可以直接在传递给 的 参数中增加一个属性 :
该方法采用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于 。
例子
你可能已经注意到,、 和 是 、 和 的翻版,它们确实模仿了 的 API。
因此,如果你已经熟悉 Browser History APIs,在使用 Vue Router 时,操作历史记录就会觉得很熟悉。
值得一提的是,无论在创建路由器实例时传递什么 配置,Vue Router 的导航方法 (、、) 都能始终正常工作。
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 (侧导航) 和 (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 没有设置名字,那么默认为 。
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 配置 (带上 s):
以上案例相关的可运行代码请移步这里.
我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 组件。我们以一个设置面板为例:
- 只是一个常规组件。
- 是一个视图组件。
- 、、 是嵌套的视图组件。
注意:我们先忘记 HTML/CSS 具体的布局的样子,只专注在用到的组件上。
组件的 部分应该是类似下面的这段代码:
那么你就可以通过这个路由配置来实现上面的布局:
以上案例相关的可运行代码请移步这里.
重定向也是通过 配置来完成,下面例子是从 重定向到 :
重定向的目标也可以是一个命名的路由:
甚至是一个方法,动态返回重定向目标:
请注意,导航守卫并没有应用在跳转路由上,而仅仅应用在其目标上。在上面的例子中,在 路由中添加 守卫不会有任何效果。
在写 的时候,可以省略 配置,因为它从来没有被直接访问过,所以没有组件要渲染。唯一的例外是嵌套路由:如果一个路由记录有 和 属性,它也应该有 属性。
也可以重定向到相对位置:
重定向是指当用户访问 时,URL 会被 替换,然后匹配成 。那么什么是别名呢?
将 别名为 ,意味着当用户访问 时,URL 仍然是 ,但会被匹配为用户正在访问 。
上面对应的路由配置为:
通过别名,你可以自由地将 UI 结构映射到一个任意的 URL,而不受配置的嵌套结构的限制。使别名以 开头,以使嵌套路径中的路径成为绝对路径。你甚至可以将两者结合起来,用一个数组提供多个别名:
如果你的路由有参数,请确保在任何绝对别名中包含它们:
关于 SEO 的注意事项: 使用别名时,一定要定义规范链接.
在你的组件中使用 或 会与路由紧密耦合,这限制了组件的灵活性,因为它只能用于特定的 URL。虽然这不一定是件坏事,但我们可以通过 配置来解除这种行为:
回到我们之前的示例:
和:
我们可以通过声明 prop 来在 中删除对 的直接依赖:
然后我们可以通过设置 来配置路由将 参数作为 prop 传递给组件:
这允许你在任何地方使用该组件,使得该组件更容易重用和测试。
当 设置为 时, 将被设置为组件的 props。
对于有命名视图的路由,你必须为每个命名视图定义 配置:
当 是一个对象时,它将原样设置为组件 props。当 props 是静态的时候很有用。
你可以创建一个返回 props 的函数。这允许你将参数转换为其他类型,将静态值与基于路由的值相结合等等。
URL 将传递 作为 props 传给 组件。
请尽可能保持 函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义 props,请使用包装组件,这样 vue 才可以对状态变化做出反应。
你还可以通过 插槽 传递任意参数:
It's common for applications to have a navigation component that renders a list of RouterLink components. Within that list, we might want to style links to the currently active route differently from the others.
The RouterLink component adds two CSS classes to active links, and . To understand the difference between them, we first need to consider how Vue Router decides that a link is active.
A RouterLink is considered to be active if:
- It matches the same route record (i.e. configured route) as the current location.
- It has the same values for the as the current location.
If you're using nested routes, any links to ancestor routes will also be considered active if the relevant match.
Other route properties, such as the , are not taken into account.
The path doesn't necessarily need to be a perfect match. For example, using an would still be considered a match, so long as it resolves to the same route record and .
If a route has a , it won't be followed when checking whether a link is active.
An exact match does not include ancestor routes.
Let's imagine we have the following routes:
Then consider these two links:
If the current location path is then these would both be considered active, so the class would be applied to both links. But only the second link would be considered exact, so only that second link would have the class .
The RouterLink component has two props, and , that can be used to change the names of the classes that are applied:
The default class names can also be changed globally by passing the and options to :
See Extending RouterLink for more advanced customization techniques using the API.
在创建路由器实例时, 配置允许我们在不同的历史模式中进行选择。
hash 模式是用 创建的:
它在内部传递的实际 URL 之前使用了一个哈希字符()。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在 SEO 中确实有不好的影响。如果你担心这个问题,可以使用 HTML5 模式。
Memory 模式不会假定自己处于浏览器环境,因此不会与 URL 交互也不会自动触发初始导航。这使得它非常适合 Node 环境和 SSR。它是用 创建的,并且需要你在调用 之后手动 push 到初始导航。
虽然不推荐,你仍可以在浏览器应用程序中使用此模式,但请注意它不会有历史记录,这意味着你无法后退或前进。
用 创建 HTML5 模式,推荐使用这个模式:
当使用这种历史模式时,URL 会看起来很 "正常",例如 。漂亮!
不过,问题来了。由于我们的应用是一个单页的客户端应用,如果没有适当的服务器配置,用户在浏览器中直接访问 ,就会得到一个 404 错误。这就尴尬了。
不用担心:要解决这个问题,你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 相同的页面。漂亮依旧!
注意:以下示例假定你正在从根目录提供服务。如果你部署到子目录,你应该使用Vue CLI 的 配置和相关的路由器的 属性。你还需要调整下面的例子,以使用子目录而不是根目录(例如,将 替换为 )。
也可以使用 代替 。
对于 Node.js/Express,可以考虑使用 connect-history-api-fallback 中间件。
- 安装 IIS UrlRewrite
- 在网站的根目录下创建一个 文件,内容如下:
将此添加到你的 中:
创建一个 文件,包含在你的部署文件中:
在 vue-cli、nuxt 和 vite 项目中,这个文件通常放在名为 或 的目录下。
你可以在 Netlify 文档中找到更多关于语法的信息。你也可以创建一个 来结合其他 Netlify 功能的重定向。
在项目根目录创建一个文件,内容如下:
这有一个注意事项。你的服务器将不再报告 404 错误,因为现在所有未找到的路径都会显示你的 文件。为了解决这个问题,你应该在你的 Vue 应用程序中实现一个万能的路由来显示 404 页面。
另外,如果你使用的是 Node.js 服务器,你可以通过在服务器端使用路由器来匹配传入的 URL,如果没有匹配到路由,则用 404 来响应,从而实现回退。查看 Vue 服务器端渲染文档了解更多信息。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/13247.html