导航栏图标
导航栏添加图标
HTML 方式
在 .vitepress/config.mts
的 themeConfig.nav
配置项中添加图标 HTML:
ts
import { defineConfig } from "vitepress";
export default defineConfig({
themeConfig: {
nav: [
{
text: "<i class='iconfont icon-guide'></i> 指南",
link: "http://vp.teek.top/",
},
],
},
});
ts
import { defineConfig } from "vitepress";
export default defineConfig({
themeConfig: {
nav: [
{
text: `
<div style="display: flex; align-items: center; gap: 4px;">
<img src="your img link" alt="" style="width: 16px; height: 16px;">
<span>指南</span>
</div>
`,
link: "http://vp.teek.top/",
},
],
},
});
Teek 内置的 iconfont
仅仅是 社交图标,更多 iconfont
图标可以去 阿里巴巴矢量图标库 下载。
举个例子:
假设您已经下载了一组 iconfont
图标,其目录结构应该如下:
sh
.
├─ iconfont.css
├─ iconfont.js
├─ iconfont.json
├─ iconfont.ttf
├─ iconfont.woff
├─ iconfont.woff2
将该目录放到 .vitepress/theme/assert/iconfont
下(实际按照自己的路径存放),然后在 .vitepress/theme/index.ts
文件里引入:
ts
import "./assets/iconfont/system/iconfont.js";
import "./assets/iconfont/system/iconfont.css";
接下来在通过 <i class="iconfont icon-{xxx}"></i>
在导航栏、侧边栏等位置使用图标。
添加样式
- 使用内联样式
<i class="iconfont icon-{xxx}" style="color: var(--tk-el-color-danger)"></i>
- 自定义一个
class
,然后编写样式
组件方式
警告
组件方式不能作用在父级导航上。
上面的方法需要传入一个 HTML 标签来实现,如果有很多导航配置,那么写起来很麻烦,且可读性较差,
在 .vitepress/theme/components
自定义一个组件 NavIcon.vue
来进行封装:
vue
<!-- .vitepress/theme/components/NavIcon.vue -->
<script setup lang="ts">
import type { DefaultTheme } from "vitepress/theme";
import type { TkIconProps } from "vitepress-theme-teek";
import { useData } from "vitepress";
import { TkIcon, isClient } from "vitepress-theme-teek";
import { VPLink } from "vitepress/theme";
defineProps<DefaultTheme.NavItemWithLink & { iconProps?: TkIconProps; subMenu?: boolean }>();
const { page } = useData();
const HASH_RE = /#.*$/;
const HASH_OR_QUERY_RE = /[?#].*$/;
const INDEX_OR_EXT_RE = /(?:(^|\/)index)?\.(?:md|html)$/;
const isActive = (currentPath: string, matchPath?: string, asRegex: boolean = false) => {
if (matchPath === undefined) return false;
currentPath = normalize(`/${currentPath}`);
if (asRegex) return new RegExp(matchPath).test(currentPath);
if (normalize(matchPath) !== currentPath) return false;
const hashMatch = matchPath.match(HASH_RE);
if (hashMatch) return (isClient ? location.hash : "") === hashMatch[0];
return true;
};
const normalize = (path: string) => {
return decodeURI(path).replace(HASH_OR_QUERY_RE, "").replace(INDEX_OR_EXT_RE, "$1");
};
</script>
<template>
<div :class="{ Icon: iconProps?.icon }">
<VPLink
:class="{
VPNavBarMenuLink: !subMenu,
SubMenu: subMenu,
active: isActive(page.relativePath, activeMatch || link, !!activeMatch),
}"
:href="link"
:target="target"
:rel="rel"
:no-icon="noIcon"
tabindex="0"
>
<TkIcon v-if="iconProps?.icon" v-bind="iconProps" />
<span v-html="text"></span>
</VPLink>
</div>
</template>
<style scoped>
.VPNavBarMenuLink {
display: flex;
align-items: center;
padding: 0 12px;
line-height: var(--vp-nav-height);
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-1);
transition: color 0.25s;
}
.VPNavBarMenuLink.active {
color: var(--vp-c-brand-1);
}
.VPNavBarMenuLink:hover {
color: var(--vp-c-brand-1);
}
.tk-icon {
margin-right: 7px;
}
.SubMenu {
display: flex;
align-items: center;
border-radius: 6px;
padding: 0 12px;
line-height: 32px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-1);
white-space: nowrap;
transition:
background-color 0.25s,
color 0.25s;
}
.SubMenu:hover {
color: var(--vp-c-brand-1);
background-color: var(--vp-c-default-soft);
}
</style>
然后在 .vitepress/theme/index.ts
里全局注册
ts
// .vitepress/theme/index.ts
import Teek from "vitepress-theme-teek";
import "vitepress-theme-teek/index.css";
import NavIcon from "./components/NavIcon.vue";
export default {
extends: Teek,
Layout: Teek.Layout,
enhanceApp({ app }) {
app.component("NavIcon", NavIcon);
},
};
最后在 themeConfig.nav
使用:
ts
import { defineConfig } from "vitepress";
export default defineConfig({
themeConfig: {
nav: [
{
component: "NavIcon",
props: {
text: "指南",
link: "/guide/intro",
activeMatch: "/01.指南/",
iconProps: {
icon: "https://vp.teek.top/teek-logo-mini.svg",
iconType: "img",
},
},
},
{
text: "资源",
items: [
{
component: "NavIcon",
props: {
text: "案例",
link: "/case",
subMenu: true,
iconProps: {
icon: "https://vp.teek.top/teek-logo-mini.svg",
iconType: "img",
size: 12, // 大小
},
},
},
{
component: "NavIcon",
props: {
text: "常见问题",
link: "/theme/qa",
subMenu: true,
iconProps: {
icon: "https://vp.teek.top/teek-logo-mini.svg",
iconType: "img",
},
},
},
],
},
],
},
});
NavIcon
组件的props
里的配置项和VitePress
的nav
配置项一致iconProps
是TkIcon
组件的props
,更多具体 API 用法请参考 TkIcon 组件