router-link
在 Vue Router 中,<router-link> 组件用于创建导航链接。它有多个属性,其中 path 和 query 属性用于指定导航目标和传递查询参数。
<router-link> 的 to 属性
<router-link> 使用 to 属性来定义导航目标。to 属性可以是一个字符串或一个对象。
字符串形式
当 to 是一个字符串时,它代表路径:
1
|
<router-link to="/about">About</router-link>
|
对象形式
当 to 是一个对象时,你可以指定路径和查询参数等:
1
|
<router-link :to="{ path: '/about', query: { plan: 'premium' } }">About</router-link>
|
path 和 query 属性详解
path 属性
path 属性指定导航的目标路径。例如:
1
|
<router-link :to="{ path: '/about' }">About</router-link>
|
query 属性
query 属性用于指定查询参数,它是一个对象。例如:
1
|
<router-link :to="{ path: '/about', query: { plan: 'premium' } }">About</router-link>
|
在这个例子中,生成的 URL 会是 /about?plan=premium。
示例
综合使用 path 和 query 属性:
1
2
3
4
5
|
<template>
<div>
<router-link :to="{ path: '/user', query: { id: 123, name: 'John' } }">User Profile</router-link>
</div>
</template>
|
这个链接会导航到 /user?id=123&name=John。
完整示例
下面是一个完整的 Vue 组件示例,展示如何使用 path 和 query 属性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<template>
<div>
<h1>Navigation Links</h1>
<router-link to="/">Home</router-link>
<router-link :to="{ path: '/about' }">About</router-link>
<router-link :to="{ path: '/contact', query: { ref: 'newsletter' } }">Contact</router-link>
<router-link :to="{ path: '/profile', query: { user: 'john', age: 30 } }">Profile</router-link>
</div>
</template>
<script>
export default {
name: 'App'
};
</script>
|
总结
- 使用
to 属性来定义导航目标,可以是字符串或对象。
- 使用
path 属性指定目标路径。
- 使用
query 属性传递查询参数。
通过这些属性,你可以轻松地创建动态导航链接,满足各种导航需求。
自定义router-link
通过自定义 router-link 组件,可以实现更多样化的样式和行为控制。你展示的代码片段使用了 custom 属性来定义一个插槽,并手动处理导航行为和样式。
解释代码片段
v-bind="$props": 传递所有 props 给 router-link。
custom: 启用 custom 模式,使得 router-link 不会自动生成一个 <a> 标签,而是允许你自定义内容。
v-slot="{ isActive, href, navigate }": 使用插槽属性接收 isActive(是否处于激活状态)、href(目标链接)和 navigate(导航函数)。
完整示例
结合你的代码片段,以下是如何将其集成到组件中的完整示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<template>
<el-sub-menu v-if="item.children && item.children.length > 0" :index="String(item.id)">
<template #title>
<Icon :icon="item.meta.icon" />
<span>{{ item.meta.title }}</span>
</template>
<my-menu-item v-for="citem in item.children" :item="citem" :key="citem.id"></my-menu-item>
</el-sub-menu>
<router-link
v-else
v-bind="$props"
custom
v-slot="{ isActive, href, navigate }"
>
<a
v-bind="$attrs"
:href="href"
@click="navigate"
:class="isActive ? activeClass : inactiveClass"
>
<el-menu-item :index="String(item.id)">
<template #title>
<Icon :icon="item.meta.icon" />
<span>{{ item.meta.title }}</span>
</template>
</el-menu-item>
</a>
</router-link>
</template>
<script setup lang="ts">
import { MenuItem } from "@/types/component/menuItem";
import { Icon } from '@iconify/vue';
// 使用 defineOptions 关闭 inheritAttrs
defineOptions({
inheritAttrs: false,
});
// 定义 props
const props = defineProps<{
item: MenuItem;
}>();
const to = computed(() => {
return props.item.path ? { path: props.item.path } : null;
});
// 定义类名
const activeClass = 'menu-item-active';
const inactiveClass = 'menu-item-inactive';
</script>
<style>
.no-underline {
text-decoration: none;
}
.menu-item-active {
/* 添加激活状态的样式 */
}
.menu-item-inactive {
/* 添加非激活状态的样式 */
}
</style>
|
解释
- 自定义
router-link: 使用 custom 模式和插槽属性 isActive, href, navigate 自定义内容。
- 样式处理: 使用
activeClass 和 inactiveClass 定义激活和非激活状态的样式类。
v-bind="$props" 和 v-bind="$attrs": 分别将所有 props 和 attrs 传递给 router-link 和 <a> 标签。
navigate 方法: 确保点击事件正确触发导航。
这种方法允许你完全控制导航行为和样式,同时确保链接行为与 Vue Router 的一致性。
扩展router-link的props并支持类型限定
为了在使用 TypeScript 时为 ...RouterLink.props 添加类型限定,你需要在 defineProps 中明确指定属性的类型。可以通过创建一个类型定义并将其与 RouterLink 的属性结合使用来实现。
实现步骤
- 导入
RouterLink 的属性类型。
- 定义一个包含你希望扩展的属性类型的接口。
- 结合
RouterLink 的属性类型与自定义属性类型。
示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<script setup lang="ts">
import { RouterLink, RouterLinkProps } from 'vue-router';
import { defineProps } from 'vue';
// 定义一个包含 RouterLink 属性和自定义属性的类型
interface CustomRouterLinkProps extends RouterLinkProps {
inactiveClass?: string;
}
// 使用 TypeScript 定义属性
const props = defineProps<CustomRouterLinkProps>();
// 计算属性等逻辑
const to = computed(() => {
return props.to ? { path: props.to as string } : null;
});
const activeClass = 'menu-item-active';
const inactiveClass = props.inactiveClass || 'menu-item-inactive';
</script>
|
解释
-
导入类型:
1
|
import { RouterLink, RouterLinkProps } from 'vue-router';
|
-
定义接口:
1
2
3
|
interface CustomRouterLinkProps extends RouterLinkProps {
inactiveClass?: string;
}
|
-
在 defineProps 中使用自定义类型:
1
|
const props = defineProps<CustomRouterLinkProps>();
|
完整示例
结合你的代码结构,以下是完整的示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
<template>
<el-sub-menu v-if="item.children && item.children.length > 0" :index="String(item.id)">
<template #title>
<Icon :icon="item.meta.icon" />
<span>{{ item.meta.title }}</span>
</template>
<my-menu-item v-for="citem in item.children" :item="citem" :key="citem.id"></my-menu-item>
</el-sub-menu>
<router-link
v-else
v-bind="$props"
custom
v-slot="{ isActive, href, navigate }"
>
<a
v-bind="$attrs"
:href="href"
@click="navigate"
:class="isActive ? activeClass : inactiveClass"
>
<el-menu-item :index="String(item.id)">
<template #title>
<Icon :icon="item.meta.icon" />
<span>{{ item.meta.title }}</span>
</template>
</el-menu-item>
</a>
</router-link>
</template>
<script setup lang="ts">
import { RouterLink, RouterLinkProps } from 'vue-router';
import { defineProps } from 'vue';
import { MenuItem } from "@/types/component/menuItem";
import { Icon } from '@iconify/vue';
// 使用 defineOptions 关闭 inheritAttrs
defineOptions({
inheritAttrs: false,
});
// 定义一个包含 RouterLink 属性和自定义属性的类型
interface CustomRouterLinkProps extends RouterLinkProps {
inactiveClass?: string;
}
// 使用 TypeScript 定义属性
const props = defineProps<CustomRouterLinkProps>();
// 计算属性等逻辑
const to = computed(() => {
return props.to ? { path: props.to as string } : null;
});
const activeClass = 'menu-item-active';
const inactiveClass = props.inactiveClass || 'menu-item-inactive';
</script>
<style>
.no-underline {
text-decoration: none;
}
.menu-item-active {
/* 添加激活状态的样式 */
}
.menu-item-inactive {
/* 添加非激活状态的样式 */
}
</style>
|
总结
通过导入 RouterLink 的属性类型并创建一个自定义类型接口,你可以在 defineProps 中为扩展属性添加类型限定。这种方法确保了代码的类型安全性和可维护性。
router-link的v-slot属性接收的数据
在 Vue Router 中,<router-link> 组件使用 v-slot 提供了一些插槽属性,这些属性包含了关于链接状态和导航的有用信息。具体来说,当你使用 custom 属性时,<router-link> 组件会向插槽传递一个对象,该对象包含 isActive, href, 和 navigate 等属性。
这些属性的数据来源如下:
isActive: 一个布尔值,指示当前链接是否处于激活状态(即,当前路由是否与该链接匹配)。
href: 生成的链接 URL,基于传递给 to 属性的目标路径。
navigate: 一个方法,用于执行导航操作,当用户点击链接时调用此方法来进行路由导航。
数据传递的过程
当你在 <router-link> 组件中使用 v-slot 和 custom 属性时,<router-link> 会传递这些插槽属性给你定义的内容。这是 Vue Router 内部实现的一部分,确保你可以完全自定义链接的渲染方式,同时保留路由导航功能。
代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
<template>
<router-link
v-else
v-bind="$props"
custom
v-slot="{ isActive, href, navigate }"
>
<a
v-bind="$attrs"
:href="href"
@click="navigate"
:class="isActive ? activeClass : inactiveClass"
>
<el-menu-item :index="String(item.id)">
<template #title>
<Icon :icon="item.meta.icon" />
<span>{{ item.meta.title }}</span>
</template>
</el-menu-item>
</a>
</router-link>
</template>
<script setup lang="ts">
import { RouterLink, RouterLinkProps } from 'vue-router';
import { defineProps } from 'vue';
import { MenuItem } from "@/types/component/menuItem";
import { Icon } from '@iconify/vue';
// 使用 defineOptions 关闭 inheritAttrs
defineOptions({
inheritAttrs: false,
});
// 定义一个包含 RouterLink 属性和自定义属性的类型
interface CustomRouterLinkProps extends RouterLinkProps {
inactiveClass?: string;
}
// 使用 TypeScript 定义属性
const props = defineProps<CustomRouterLinkProps>();
// 计算属性等逻辑
const to = computed(() => {
return props.to ? { path: props.to as string } : null;
});
const activeClass = 'menu-item-active';
const inactiveClass = props.inactiveClass || 'menu-item-inactive';
</script>
<style>
.no-underline {
text-decoration: none;
}
.menu-item-active {
/* 添加激活状态的样式 */
}
.menu-item-inactive {
/* 添加非激活状态的样式 */
}
</style>
|
在这个示例中,<router-link> 使用 custom 属性并定义了一个插槽,该插槽接收三个属性:
isActive: 当前链接是否处于激活状态。
href: 生成的链接 URL。
navigate: 一个方法,用于执行导航。
这些属性是由 Vue Router 的 <router-link> 组件内部传递的。使用这些属性,你可以完全自定义链接的外观和行为,同时确保路由导航功能正常工作。
总结
通过 v-slot="{ isActive, href, navigate }",你可以从 Vue Router 的 <router-link> 组件中获取到关于链接状态和导航功能的上下文数据。Vue Router 通过 custom 模式提供这些数据,以便你可以灵活地自定义链接的渲染和交互行为。