切换导航
简历
工具
演示
查询
导航菜单
服务端
30
前端
114
数据库
82
进阶开发
8
桌面程序
2
QA
15
软件使用
36
规范协议
5
操作系统
11
AI
0
复用资源
6
硬件
0
标签
HTML
正则表达式
Json
包管理工具
vite
CSS
XPath
JavaScript
Jquery
less
ES6
Vue
React
vue 3
Layui
editor.md
sea.js
Zepto.js
mysql.js
mssql.js
NodeJs
Express
前端template
YAML
杂项
外部链接
.NET Core SDK和运行时安装包
淘宝 NPM 镜像
查询网
Tables Generator线上表格转换工具
引用cdn在线脚本和样式
首页
前端
Vue Router 中RouterLink和RourerView
[TOC] ## RouterLink / router-link ### 匹配当前路由的链接 应用程序通常都会有一个渲染 RouterLink 列表的导航组件。我们也许想对这个列表中匹配当前路由的链接进行视觉区分。 RouterLink 组件会为匹配当前路由的链接添加两个 CSS 类,`router-link-active` 和 `router-link-exact-active`。要理解它们之间的区别,我们首先需要了解 Vue Router 如何判断一个链接是匹配当前路由的。 #### 链接在什么时候匹配当前路由 当满足以下条件时,RouterLink 被认为是匹配当前路由的: + 它与当前路径匹配相同的路由记录(即配置的路由)。 + 它的 params 与当前路径的 params 相同。 如果你使用了嵌套路由,任何指向祖先路由的链接也会被认为是匹配当前路由的,只要相关的 params 匹配。 > Tips:这里如果父级有 params 参数,那么子级匹配上,要想父级也匹配上,那它的参数值也要一样,例如下面的示例 ```HTML <!--父级{如果这里传的params.name不是【刘玄德】,而是别的父级也不会命中匹配哦}--> <router-link :to="{ name: 'routerStudy', params: { name: '刘玄德' } }">路由参数</router-link> <!--子级--> <RouterLink :to="{ name: 'routerStudy3', params: { name: '刘玄德' } }">切换到【刘玄德】</RouterLink> ``` 路由设置 ```js path: '/routerStudy/:name', name: 'routerStudy', component: () => import('@study/RouterStudy.vue'), children: [{ path: 'cur', name: 'routerStudy3', component: () => import('@study/RouterStudy.vue') }] ``` 示例可查看[路由参数](http://vue.cylyccjy.com/routerStudy/%E5%88%98%E7%8E%84%E5%BE%B7/cur) 其他路由属性,例如 query,不会被考虑在内。 路径不一定需要完全匹配。例如,使用 alias 仍然会被认为是匹配的,只要它解析到相同的路由记录和 params。 如果一个路由有 redirect,在检查链接是否匹配当前路由时不会跟随重定向。 #### 精确匹配当前路由的链接 精确匹配不包括祖先路由。 假设我们有以下路由: ```js const routes = [ { path: '/user/:username', component: User, children: [ { path: 'role/:roleId', component: Role, }, ], }, ] ``` 然后考虑这两个链接: ```HTML <RouterLink to="/user/erina"> User </RouterLink> <RouterLink to="/user/erina/role/admin"> Role </RouterLink> ``` 如果当前路径是 /user/erina/role/admin,那么这两个链接都会被认为是匹配当前路由的,因此 router-link-active 类会应用于这两个链接。但只有第二个链接会被认为是精确的,因此只有第二个链接会有 router-link-exact-active 类。 > tips:上面 RouterLink 匹配到之后的a标签class展示 ```HTML <a data-v-7a7a37b1="" href="/settings" class="router-link-active">嵌套视图</a> <a data-v-7a7a37b1="" href="/settings/v3" class="router-link-active router-link-exact-active" aria-current="page">嵌套视图v3</a> ``` #### 配置类名 RouterLink 组件有两个属性,activeClass 和 exactActiveClass,可以用来更改应用的类名: ```HTML <RouterLink activeClass="border-indigo-500" exactActiveClass="border-indigo-700" ... > ``` 默认的类名也可以通过传递 linkActiveClass 和 linkExactActiveClass 选项给 createRouter() 来全局更改: ```JS const router = createRouter({ linkActiveClass: 'border-indigo-500', linkExactActiveClass: 'border-indigo-700', // ... }) ``` #### exact 属性 exact 是 `<router-link>` 组件的一个布尔属性,用于控制激活类(active class)的匹配逻辑,router-link 默认无 exact **添加 exact 后的行为** + 启用精确匹配:只有当前路由的路径完全等于链接的路径时,才会添加激活类。 + router-link-active 和 router-link-exact-active 类都只会在此完全匹配时出现(实际默认的 exact-active-class 本身就是精确匹配专用类,但 exact 同时抑制了前缀匹配)。 + 示例: ```HTML <router-link to="/users" exact>用户</router-link> ``` 当前路径为 /users → 高亮; 当前路径为 /users/123 → 不高亮。 **常见的应用场景** + 导航菜单的首页:避免在任意子路径下都高亮“首页”链接 ```HTML <router-link to="/" exact>首页</router-link> ``` + 严格区分的同级路由:例如 /about 和 /about/team,希望前者只在精确匹配时高亮 > 设置 exact 后,仅精确匹配才应用 active-class,相当于把匹配条件收紧到完全相等 [========] ### 自定义链接组件 useLink `useLink` 是 Vue Router 提供的一个组合式 API 函数,它**将 `<router-link>` 组件的内部逻辑暴露出来**,让你可以创建自己的自定义链接组件。 简单理解,当你需要做一个特殊的链接按钮(比如带有复杂样式、图标、或特定交互的导航元素),但又想复用 `<router-link>` 的**路由跳转逻辑**和**路由状态激活判断**时,`useLink` 就是最佳选择。 #### `useLink` 的作用与返回对象 **作用:** 接收一个 `props` 对象(通常包含 `to` 等路由信息),并返回一个包含路由链接核心状态和方法的对象。 **返回值对象包含的属性和方法:** | 属性/方法名 | 类型 | 说明 | | :--- | :--- | :--- | | **`route`** | `Object` | 解析后的路由位置对象,包含了 `path`, `query`, `params` 等信息。 | | **`href`** | `ComputedRef<string>` | 计算属性,表示最终要跳转的完整路由路径。 | | **`isActive`** | `ComputedRef<boolean>` | 计算属性,当当前路由匹配时(包括嵌套路由),值为 `true`。 | | **`isExactActive`** | `ComputedRef<boolean>` | 计算属性,更严格的匹配,只有当当前路由完全匹配时,值才为 `true`。 | | **`navigate`** | `Function` | 导航函数,调用它会触发路由跳转。直接将它绑定到 DOM 元素的点击事件上即可。 | #### `useLink` 创建自定义链接组件 下面是一个完整的例子,创建一个名为 `CustomLink.vue` 的自定义链接组件,它实现了激活状态的样式控制,并支持外部链接跳转。 ```HTML <template> <!-- 1. 组件渲染一个 <a> 标签,而不是 <router-link>。 2. 将 useLink 提供的 href 绑定到 href 属性上。 3. 将 useLink 提供的 navigate 绑定到 @click 事件上,处理路由跳转。 4. 动态绑定一个类,用于高亮激活状态的链接(比如给当前页面的链接加粗、变色)。 --> <a :href="href" @click="navigate" :class="{ 'text-blue-600 font-bold': isActive, // 当链接匹配时,应用激活样式 'text-gray-600': !isActive // 未激活时的样式 }" class="px-4 py-2 rounded transition-colors duration-200" > <!-- 使用插槽,让父组件可以传入自定义内容,如文字或图标 --> <slot></slot> <!-- 可选:当完全匹配时显示一个小圆点作为提示 --> <span v-if="isExactActive" class="ml-2 w-2 h-2 bg-blue-500 inline-block rounded-full"></span> </a> </template> <script setup> // 1. 从 'vue-router' 中导入 useLink 工具函数。 import { useLink } from 'vue-router' // 2. 定义组件的 props,这是使用 useLink 的前提。 // props 需要接收 RouterLink 支持的所有参数,其中 'to' 是必须的。 // 使用 ...RouterLink.props 可以方便地继承所有官方属性,避免遗漏。 const props = defineProps({ // 方式一(推荐):直接继承官方 RouterLink 的所有 prop 定义 // 这样我们的 CustomLink 组件就支持 to, replace, activeClass 等所有官方参数了。 ...useRouterLinkProps(), // 注意:这里假设有个辅助函数,下面会解释。为了清晰,我们先手动写核心的 to。 // 方式二(更清晰):手动写出核心的 props,以便理解 to: { type: [String, Object], required: true }, replace: { type: Boolean, default: false }, // ... 其他你需要的 props }) // 为了代码整洁,最佳实践是使用 Vue Router 提供的辅助函数来获取完整的 props 定义。 // 注意:在 <script setup> 中,你需要先导入它。 import { RouterLink } from 'vue-router' // 3. 核心步骤:调用 useLink 并传入 props。 // useLink 会解析 props(比如 to、replace 等), // 并返回我们需要的所有响应式属性和导航方法。 const { href, navigate, isActive, isExactActive, route } = useLink(props) // 4. (可选) 扩展功能:处理外部链接。 // 如果 to 的值是 http 开头的字符串,那么应该使用原生跳转,而不是 Vue Router 的 navigate。 const isExternalLink = computed(() => { return typeof props.to === 'string' && props.to.startsWith('http') }) // 5. (可选) 重写点击处理逻辑。 // 如果是外部链接,就不调用 useLink 返回的 navigate,而是走原生行为。 const handleClick = (event) => { if (isExternalLink.value) { // 如果是外部链接,直接跳转即可 window.location.href = href.value return } // 否则,使用 Vue Router 的导航函数 navigate(event) } </script> // 注意:上述代码中 useRouterLinkProps 并非真实 API,为了完整性,正确的继承 props 方式如下: // 在 <script setup> 外部或内部定义: /* const props = defineProps({ // 手动合并:将 RouterLink 的 props 与你自己的 props 合并 ...RouterLink.props, // 添加你自己的自定义 prop customVariant: String }) */ ``` 现在,你就可以在任何地方像使用普通组件一样使用 `CustomLink` 了: ```HTML <template> <div class="flex gap-4"> <!-- 使用自定义链接组件 --> <CustomLink to="/">首页</CustomLink> <CustomLink to="/about">关于我们</CustomLink> <CustomLink to="https://vuejs.org">Vue官网</CustomLink> </div> </template> ``` --- > **代码注释详解** **`const { href, navigate, ... } = useLink(props)`** : 这是**最关键的一行**。`useLink` 接收我们定义的 `props` 作为参数,然后“吐出”所有构建一个路由链接所需的要素: - `href`:用于 `<a>` 标签的 `href` 属性。 - `navigate`:路由跳转函数,用于处理点击事件。 - `isActive` / `isExactActive`:用于实现高亮样式,提升用户体验。 > **注意事项** - `useLink` 旨在用于构建**自定义路由链接组件**,在普通业务组件中直接使用的场景较少。如果你只是想进行编程式导航,使用 `useRouter` 会更直接。 - 在使用 `useLink` 时,务必确保传入的 `props` 中包含 `to` 属性,否则无法正确解析目标路由。 - 如果要支持 `active-class` 等官方 `<router-link>` 的属性,你需要像示例中那样正确地继承 `RouterLink.props`。 [**扩展 RouterLink(官方自定义导航)**](https://router.vuejs.org/zh/guide/advanced/extending-router-link.html) ## RouterView / router-view ### 命名视图 有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。 + APP.vue ```html <template> <router-view class="view left-sidebar" name="LeftSidebar" /> <router-view class="view main-content" /> <router-view class="view right-sidebar" name="RightSidebar" /> </template> ``` + LeftSidebar.vue ```html <template> <h1>LeftSidebar</h1> </template> ``` + RightSidebar.vue ```html <template> <h1>RightSidebar</h1> </template> ``` + Home.vue ```html <template> <h1>Home</h1> </template> ``` 一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s): ```js const router = createRouter({ history: createWebHashHistory(), routes: [ { path: '/', components: { default: Home, // LeftSidebar: LeftSidebar 的缩写 LeftSidebar, // 它们与 `<router-view>` 上的 `name` 属性匹配 RightSidebar, }, }, ], }) ``` ### 嵌套命名视图 我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 router-view 组件。我们以一个设置面板为例: ```bash /settings/emails /settings/profile +-----------------------------------+ +------------------------------+ | UserSettings | | UserSettings | | +-----+-------------------------+ | | +-----+--------------------+ | | | Nav | UserEmailsSubscriptions | | +------------> | | Nav | UserProfile | | | | +-------------------------+ | | | +--------------------+ | | | | | | | | | UserProfilePreview | | | +-----+-------------------------+ | | +-----+--------------------+ | +-----------------------------------+ +------------------------------+ ``` + Nav 只是一个常规组件。 + UserSettings 是一个视图组件。 + UserEmailsSubscriptions、UserProfile、UserProfilePreview 是嵌套的视图组件。 > **注意:**我们先忘记 HTML/CSS 具体的布局的样子,只专注在用到的组件上。 UserSettings 组件的 `<template>` 部分应该是类似下面的这段代码: + UserSettings.vue ```html <template> <div class="us"> <h2>User Settings</h2> <UserSettingsNav /> <router-view class="us__content" /> <router-view name="helper" class="us__content us__content--helper" /> </div> </template> <script> import UserSettingsNav from "./UserSettingsNav.vue"; export default { components: { UserSettingsNav }, }; </script> ``` + UserSettingsNav.vue ```html <template> <div class="us__nav"> <router-link to="/settings/emails">emails</router-link> <br /> <router-link to="/settings/profile">profile</router-link> </div> </template> ``` + UserEmailSubscriptions.vue ```html <template> <div> <h3>Email Subscriptions</h3> </div> </template> ``` + UserProfile.vue ```html <template> <div> <h3>Edit your profile</h3> </div> </template> ``` + UserProfilePreview.vue ```html <template> <div> <h3>Preview of your profile</h3> </div> </template> ``` 那么你就可以通过这个路由配置来实现上面的布局: + router.js ``` js routes: [ { path: '/settings', // You could also have named views at tho top component: UserSettings, children: [ { path: 'emails', component: UserEmailsSubscriptions, }, { path: 'profile', components: { default: UserProfile, helper: UserProfilePreview, }, }, ], }, ], ```
扫一扫手机看
点击排行
windows 文件资源管理器使用
Layui 弹窗open使用说明
SQL Server 中字符串函数使用
C# 使用QQ邮箱代理做邮件接收功能
SQL Server关于apply的两种形式cross apply 和 outer apply
ASP.NET MVC 模型的自定义验证
nvm安装及常用命令
SQL Server 中数据类型转换
SQL Server 中WITH AS短语的使用
IE浏览器下AJAX缓存问题导致数据不更新的解决办法
订阅号