VuePress主题教程 -- Tag标签页

Tag标签页和分类页非常相似,也是标签汇总页加上具体标签的文章列表页组合而成,同样是借助vuepress的extendPageData插件api动态注入页面类型和blog插件君打的一套组合拳。

# 目标效果

  • 通过设置文档的$frontmattertag或tagskey,自动汇总到标签页;
  • 对每个标签进行文章计数;
  • 点击标签进入具体标签的文章列表页;
  • 文章列表页支持分页;

# blog插件配置

SideBar模板(一)--SubNav一篇中,我们已经做过配置;

# 动态注入页面类型












 
 
 
 
 



// docs/.vuepress/theme/plugin/util/index.js

module.exports = {
  // ...
  extendPageData($page) {
    if ($page.path === '/archives/') {
      return $page.pageType = 'archive';
    } else if ($page.path === '/categories/') {
      return $page.pageType = 'category';
    } else if (/^\/categories\/\w/.test($page.path)) {
      return $page.pageType = 'categoryItem';
    } else if ($page.path === '/tags/') {
      return $page.pageType = 'tag';
    } else if (/^\/tags\/\w/.test($page.path)) {
      return $page.pageType = 'tagItem';
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 改造Layout布局组件









 
 









 
 










 
 







// docs/.vuepress/theme/layouts/Layout.vue
<template>
  <div class="theme-container">
    <SideBar/>
    <Post v-if="$page.pid === 'post'"/>
    <Archive v-else-if="$page.pageType === 'archive'"/>
    <Category v-else-if="$page.pageType === 'category'" />
    <CategoryItem v-else-if="$page.pageType === 'categoryItem'" />
    <Tag v-else-if="$page.pageType === 'tag'" />
    <TagItem v-else-if="$page.pageType === 'tagItem'" />
    <Home v-else />
    <SvgSprite/>
  </div>
</template>
<script>
import Post from '../components/Post'
import Archive from '../components/Archive'
import Category from '../components/Category'
import CategoryItem from '../components/CategoryItem'
import Tag from '../components/Tag.vue'
import TagItem from '../components/TagItem.vue'
import Home from '../components/Home'
import SideBar from '../components/SideBar'
import SvgSprite from '../components/SvgSprite.vue'
export default {
  name: 'Layout',
  components: {
    Home,
    Archive,
    Category,
    CategoryItem,
    Tag,
    TagItem,
    SideBar,
    Post,
    SvgSprite
  }
}
</script>
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

# 编写Tag模板

// docs/.vuepress/theme/components/Tag.vue
<template>
  <div class="theme-main__inner theme-tag">
    <div class="theme-tag__list">
      <h2 class="theme-tag__title">{{$tag.list.length}} tags in total</h2>
      <router-link class="theme-tag__link" v-for="tag in $tag.list" :key="tag.name" :to="tag.path"># {{ tag.name }} [{{tag.pages.length}}]</router-link>
    </div>
  </div>
</template>
<script>
export default {
  name: 'Tag'
}
</script>
<style lang="stylus">
.theme-tag
  border-radius: 6px;
  padding: 2.15rem;
  &__title
    margin 0 0 1.5rem 0
    font-size: 1.78571rem;
    font-weight normal
  &__link
    display inline-block
    padding: 0 1em;
    border-radius: 3px;
    line-height: 2.4;
    margin: 0 1rem 1rem 0;
    &:hover
      color #333
  
</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

TIP

$tag是blog插件君暴露的计算属性,包含了全站的标签信息,遍历list输出所有标签,item.pages包含了具体标签下的文档页数组,它的length正好就是我们需要的具体标签下的文章计数。

运行结果如下:

截图

# 编写TagItem模板

// docs/.vuepress/theme/components/TagItem.vue
<template>
  <div class="theme-main__inner tag-item">
    <h1 class="tag__title"># {{$currentTag.key}}</h1>
    <div class="post-list">
      <a class="post-list__item" :href="item.path" v-for="item in postList" :key="item.date">
        <span class="post-list__date">{{item.date}}</span>
        <span class="post-list__title">{{item.title}}</span>
      </a>
    </div>
    <Pagination v-if="$pagination.length > 1"/>
  </div>
</template>
<script>
import { Pagination } from '@vuepress/plugin-blog/lib/client/components';
export default {
  name: 'TagItem',
  components: {
    Pagination
  },
  computed: {
    postList() {
      let list = [];
      this.$pagination.pages.map(item => {
        const date = new Date(item.frontmatter.date);
        list.push({
          ...item,
          date: `${date.toLocaleDateString()}`
        })
      });
      list.sort((a, b) => {
        return new Date(b.date) - new Date(a.date);
      })
      return list;
    }
  }
}
</script>
<style lang="stylus">
.tag-item
  border-radius: 6px;
  padding: 2.15rem;
</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

TIP

$currentTag是blog插件君给暴露的计算属性,顾名思义表示当前标签。$pagination是blog插件君给暴露的另外个有用的属性,$pagination.pages包含了当前标签下的文章列表数组,这里对显示时间格式及排序做了下简单的处理。<Pagination/>组件是blog插件君提供的内置分页组件,我们可以直接拿出来使用。

运行结果如下:

截图

# 最后

至此,标签页就差不多完成了,基本与分类页是一个模子,计算属性和blog插件君一如既往的可靠。