1980's Maker

一个出生于80年代的程序员 -- 喜爱创[客]、美[食]、动[画]、怀[旧]的新手艺人的博客

VuePress 主题教程 -- NavBar 模板文件编写

导航模块是博客站点必备的一个元素,我们将参考VuePress默认主题来实现导航模块。

# 开始编写

导航将实现的功能

  • 自定义导航文案及链接。
  • 页面激活时进行高亮显示。
  • 自动区分内、外部链接。

导航数据来源于主题配置项,我们先配置上数据:








 
 
 
 
 




// docs/.vuepress/config.js
module.exports = {
  title: 'hello vuepress',
  description: '我的第一个vupress站点',
  port: 8088,
  theme: require('./theme/index'),
  themeConfig: {
    nav: [
      { text: '🏠 Home', link: '/' },
      { text: '🏠 内部链接', link: '/2021/03/02/one/' },
      { text: '🔥 外部链接(External)', link: 'https://google.com' },
    ],
    copyright: `© ${new Date().getFullYear()} ❤️ <a target="_blank" rel="external nofollow noopener" href="https://17ria.com/">Neil Chen</a>`
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

TIP

在这里导航菜单数据格式用的是对象数组,足够灵活,方便扩展。 eg.假设后面导航需要设置icon,只须加个icon的key扩展即可。

# 引入工具函数

区分内、外部链接的方法函数我们可以写在工具函数里

// /Users/mingangchen/Documents/spare_time/vuepress-starter/docs/.vuepress/theme/utils/help.js (git)
export const outboundRE = /^[a-z]+:/i

export function isExternal (path) {
  return outboundRE.test(path)
}
1
2
3
4
5
6

继续编写NavBar模板文件,得益于Vue组件系统的加持,我们把导航菜单的结点提取成一个子组件NavLink来负责一部分渲染职责。

// docs/.vuepress/theme/components/NavLink.vue
<template>
  <a
    v-if="isExternal"
    :href="item.link"
    class="nav-link external"
    :target="target"
    :rel="rel"
  >
    {{ item.text }}
    <OutboundLink v-if="isBlankTarget" />
  </a>
  <router-link v-else class="nav-link" :to="item.link">{{item.text}}</router-link>
</template>

<script>
import { isExternal } from '../utils/help'
export default {
  name: 'NavLink',
  props: {
    item: {
      required: true
    }
  },
  computed: {
    isExternal() {
      return isExternal(this.item.link)
    },
    isBlankTarget () {
      return this.target === '_blank'
    },
    target () {
      if (this.item.target) {
        return this.item.target
      }
      return isExternal(this.item.link) ? '_blank' : ''
    },
    rel () {
      if (this.item.rel) {
        return this.item.rel
      }
      return this.isBlankTarget ? 'noopener noreferrer' : null
    }
  }
}
</script>
<style lang="stylus">
.nav-link
  &.router-link-exact-active
    background-color yellow
    color red
</style>
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

主题教程开始时有介绍VuePress的其中一个组成部分是Vue Router。依托于Vue Router,导航的高亮显示只需要样式便可以完成,假如当前页面的路由精确匹配到导航里配置的菜单时,<a>标签会自动添加名为router-link-exact-active的className。详细请参考vue-router文档 (opens new window)

TIP

OutboundLink(用来标识外部链接)也是vuepress的内置组件,可以直接使用。样式我们这里用的stylus(vuepress的默认样式预处理工具),stylus的语法很包容,既可以用完整的原生css格式也可以用极简的python缩进风格,不清楚的可以参考stylus文档 (opens new window)

// docs/.vuepress/theme/components/NavBar.vue
<template>
  <nav>
    <NavLink v-for="item in $themeConfig.nav" :item="item"/>
  </nav>
</template>

<script>
import NavLink from './NavLink'
export default {
  name: 'NavBar',
  components: {
    NavLink
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 最后将NavBar放置到SideBar中





 





 




 




// docs/.vuepress/theme/components/SideBar.vue
<template>
  <div>
    SideBar {{$site.title}}
    <NavBar/>
    <FooterBar/>
  </div>
</template>
<script>
import FooterBar from './FooterBar'
import NavBar from './NavBar'
export default {
  name: 'SideBar',
  components: {
    FooterBar,
    NavBar
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

运行效果:

分页截图

# 结束

至此,NavBar模板文件就完成了,相对简陋。还有好些没有继续展开,比如默认主题的导航下拉菜单。

Buy me a cup of coffee ☕.