preface

The previous chapter showed how the Vuepress theme implements inheritance, so you can modify any component and style of the default theme. We know that vuepress is not automatically available according to our Markdown file

---
tags:
- js
- vue
---
Copy the code

Generate tag cloud page, and a blog, tags in which the knowledge classification and navigation function, is an essential link, the following lead you to transform the default theme to enable it to support automatic generation of tag cloud page

Step 1 Configuration modification

Since it’s a theme, you need to provide customizability, and if someone doesn’t need the tag functionality, they need to meet that requirement by opening the config.js file and modifying the configuration in it

themeConfig: { ... tags:"/tags", ... Nav: [{... the text: "tag clouds", link: '/ tags/' tags: true},... . }Copy the code

The reason I’m doing this is because NAV is adding a menu to the header, tags:”/tags” is defining the tag routing path, so that no matter what name my tag is defined by, I can navigate to the right location.

The second step is folder creation

Since vuepress generates routes based on the Markdown file, a page that wants to generate a tag must also create a Markdown file. Create a tags folder under the.vuepress folder with a new readme.md file. Restart the project to see

Step 3 create a Tags component

In docs /. / vuepress/theme components under the new Tags. The vue file. In order for pages to automatically integrate with tag components, you need to modify the Layout.vue component. Now copy the default theme Layout components to the docs /. / layouts vuepress/theme directory (if you don’t know how to copy the Layout of the default theme please see previous section), modify one

. </Sidebar> <! - the sidebar - > < Home v - if = "$page. The frontmatter. Home" / > <! <Tags v-else-if=" Tags "/> <Page v-else :sidebar-items="sidebarItems" > <slot name="page-top" slot="top" /> <slot name="page-bottom" slot="bottom" /> </Page> ...Copy the code

The determination of tags variables in script

export default {
  ...
  data() {
    return{... tags:false}},...created(){
    this.checkTags()
  }
  ...
  checkTags() {
      path=this.$route.path
      let tags = this.$site.themeConfig.nav.filter(v => v.tags); / / determine tagsif (tags[0].link === path) {
        this.tags = true;
        this.$page.frontmatter.sidebar = false; // Tags do not need a sidebar}else {
        this.tags = false; } // Check whether it is a category pagelet type = this.$page.frontmatter.type;

      if (type= = ="classify") {
        this.type = "classify";
        this.$page.frontmatter.sidebar = false; // Tags do not need a sidebar}else {
        this.type = "";
      }
      if (this.$page.frontmatter.defaultHome) {
        this.$page.frontmatter.sidebar = false; // The home page does not need a sidebar}}}Copy the code

Import the Tags component, where Tags determine whether the current page routing Tags are true, an option configured in config.js. Add the following content to the newly created Tags. Vue file. This is the tag component defined by me, and you can modify it according to my component

<template> <div> <div class="content default"></div> <div class="tag"> <div class="items"> <span v-for="taginfo in tags"  :style="{backgroundColor:color()}" @click="change(taginfo.tag)" :class="taginfo.tag===tg? 'active':''" >{{taginfo.tag}}({{taginfo.number}})</span> </div> <div class="article-list"> <Article v-for="tag in info" :tag="tag" :tg="tg" @turnTo="change"/> </div> </div> </div> </template> <script> import Article from "@theme/components/Article.vue"; export default { components: { Article }, data() { return { info: [], tg: "" }; }, computed: {tags() {// core code, integrate the number of tags in markDown let allTags = []; this.$site.pages.forEach(v => { if (v.frontmatter.tags) { allTags.push(v.frontmatter.tags); } else if (v.frontmatter.tag) { allTags.push(v.frontmatter.tag); }}); allTags = allTags.join(",").split(","); let flatTags = Array.from(new Set(allTags)); return flatTags.reduce((res, v) => { let o = {}; o.tag = v; o.number = allTags.filter(value => value === v).length; res.push(o); return res; } []); }}, methods: {change(tag) {this.tg = tag;}}, methods: {change(tag) { this.info = this.$site.pages.filter(v => { let tags = v.frontmatter.tags; if (tags) { return tags.some(v => v === tag); }}); }, color () {/ / tag button color let colors = [" # 3498 db ", "# 3 eaf7c", "# 5 cbbf6", "# f5A28E", "# f2AC3B", "# FA6551", "#C68CE0" ]; return colors[parseInt(Math.random() * colors.length)]; }}, mounted() {// When routing? Let tag= this.$route.query. Tag; if (tag) { this.change(tag); }}}; Word-wrap: break-word! Important; "> < span style ='stylus' scoped>.tag {max-width: 46.rem; margin: 0 auto; 2.5 rem padding: 0; .items { margin-bottom: 2rem; span { vertical-align: middle; cursor: pointer; Margin: 0.5 rem 0.5 rem 0.2 rem. Padding: 0.4 rem 0.7 rem; display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; Border - the radius: 0.2 rem; background: #fff; color: #fff; font-size: 1rem; Box-shadow: 0 1px 0.25rem 0 hSLA (0, 0%, 57%, 0.21); box-shadow: 0 1px 0.25rem 0 hSLA (0, 0%, 57%, 0.21); The transition: all 0.3 s; background-color: red; &. Active {transform: scale (1.2); } &:hover {transform: scale(1.2); } } } } </style>Copy the code

The Article component is the part of the tag that displays the content of the Article. You can define your own component and style. I attach my own Article component

<template> <div class="abstract"> <div class="abstract-item"> <div class="text-hover"> <router-link :to="tag.path">{{tag.title}}</router-link> </div> <! ----> <div class="abstract"> <div class="tip custom-block" v-if="tag.excerpt"> <! -- <p class="custom block-title">{{tag.title}}</p> <p> </ul>--> <div v-html="tag.excerpt"></div> </div> </div> <div class="details-btn"> <router-link :to="tag.path"> <div ">< div style =" box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 13px! Important; white-space: normal; class="v-divider"></div> <div class="article-info article-info-item"> <i class="what"> <em v-if="tag.lastUpdated">{{tag.lastUpdated}}</em> </i> <i class="what" v-for="t in tag.frontmatter.tags"> <em class="text-item active" v-if="t==tg">{{t}}</em> <em class="text-item" v-else @click="$emit('turnTo',t)">{{t}}</em> </i> <! -- <i class="iconfont h-classify article-info-item" class="what" > <em class="text-item">IDE</em> </i>--> </div> </div> < div> </template> <script> export default {props: {tag: {}, // indexing data tg: ""}}; </script> <style lang="stylus" scoped> $color = #3eaf7c; .abstract { margin-top: 1rem; width: 100%; . Abstract -item {margin: 0 auto 1.2rem; Padding: 1 rem 1.2 rem; width: 100%; overflow: hidden; Border - the radius: 0.3 rem; -webkit-box-sizing: border-box; box-sizing: border-box; - its - the transition: all 0.3 s; The transition: all 0.3 s; -webkit-box-shadow: 0 0.25rem 1.2rem 0 hSLA (0, 0%, 57%, 0.21); Box-shadow: 0 0.25rem 1.2rem 0 hSLA (0, 0%, 57%, 0.21); background-color: #fff; position: relative; .abstract { } .text-hover { position: relative; The font - size: 1.2 rem; line-height: 2rem; display: inline-block; a { &:after { content: ''; position: absolute; width: 101%; height: 2px; bottom: 0; left: 0; background-color: $color; visibility: hidden; -webkit-transform: scaleX(0); transform: scaleX(0); - its - the transition: 0.3 s ease - in-out; The transition: 0.3 s ease - in-out; } &:hover:after { visibility: visible; -webkit-transform: scaleX(1); transform: scaleX(1); } } } .details-btn { text-align: right; Margin: 0.6 rem 0; .v-btn { display: inline-block; The font - size: 0.8 rem; Padding: 0.4 rem 0.7 rem; cursor: pointer; Letter - spacing: 0.1 em. - its - the transition: all 0.3 s; The transition: all 0.3 s; background-color: #efefef; color: #2c3e50; Border - the radius: 0.1 rem; The line - height: 1.2; &:hover { background-color: $color; color: #fff; } } } .article-info { margin-right: 1rem; The line - height: 1.6 rem; margin-right: 1rem; The line - height: 1.6 rem; font-style: normal; .text-item { font-weight: 700; border: 1px $color; font-style: normal; Margin - left: 0.4 rem; cursor: pointer; background-color: #f6f6f6; Padding: 0.2 rem 0.4 rem; &.active { color: $color; } &:hover { color: $color; } } } .v-divider { display: block; -webkit-box-flex: 1; -ms-flex: 1 1 0px; flex: 1 1 0px; max-width: 100%; height: 0; max-height: 0; border: solid; border-width: thin 0 0 0; -webkit-transition: inherit; transition: inherit; border-color: rgb(234, 236, 239); Margin - top: 0.7 rem; Margin - bottom: 0.7 rem; Mso-font-weight: 0pt; mso-font-weight: 0pt; mso-font-weight: 0pt; color: rgb(153, 153, 153); } </style>Copy the code

At this point, the tag cloud page is complete and looks like this

Step 4 Display the TAB page and jump to the TAB page

The Page component is the content component for the article to display. If you want to display the tag at the head of the article when the article is displayed, you need to modify the Page component.

In the components of the default theme Page. Vue file is copied to the docs /. / components vuepress/theme, modify the content

<slot name="top"/> <! <section class="tags" v-if="this.$site.themeconfig. Tags &&tags&&tags.length>0"> <! $page. Frontmatter. Tags. This is an array of tags generated by compiling tags in the Markdown file by Vuepress. --> <span class="tagPopup" v-for="tag in tags"> <! -- $site.themeconfig. Tags is the tags directory specified in config.js --> <router-link :to="'/'+$site.themeconfig. Tags +'/? tag='+tag" class="tag">{{tag}}</router-link> </span> </section> <! --> <Content/>Copy the code

The modified effect is as follows

At this point, the transformation of the tag cloud is almost complete. Here is the source address I modified: vuepress-theme-reform

Check out the results on my blog