上一章已經講了 vuepress 主題如何實現繼承,這樣咱們能夠任意修改默認主題的任何組件及樣式了。咱們知道 vuepress 是沒法自動根據咱們 markdown 文件中的html
---
tags:
- js
- vue
---
複製代碼
生成標籤雲的頁面的,而一個博客,標籤在其中有知識分類及導航功能,是必不可少的一環,下面帶領你們來改造一下默認主題讓它能支持自動生成標籤雲頁面vue
既然是主題,就要提供可定製化,若是有人不須要 tag 功能,那也須要知足需求,打開 config.js 文件,修改其中的配置git
themeConfig: {
...
tags:"/tags",
...
nav: [
...
{
text:"標籤雲",
link:'/tags/',
tags:true
},
...
]
...
}
複製代碼
我這樣配置的緣由是 nav 是給頭部目錄添加菜單,tags:"/tags"是定義標籤路由路徑,這樣無論個人標籤頁定義成什麼名字,都能導航到正確的位置。github
因爲 vuepress 是根據 markdown 文件生成的路由,因此想要生成一個標籤的頁面也必須創建一個 markdown 文件。 在.vuepress 文件夾下創建 tags 文件夾,其中新建 README.md 文件。 重啓項目 可看到web
在 docs/.vuepress/theme/components 下新建 Tags.vue 文件。 爲了使頁面自動集成 tag 組件,須要修改 Layout.vue 組件,上一節咱們講過要修改默認主題能夠用組件的繼承,如今把默認主題的 Layout 組件複製到 docs/.vuepress/theme/layouts 目錄下(若是不知道如何複製默認主題的 Layout 請看上一節),修改其中的json
...
</Sidebar>
<!-- 側邊欄 -->
<Home v-if="$page.frontmatter.home"/>
<!-- 若是md文件中有 home:true 就使用該組件 -->
<Tags v-else-if="tags"/>
<Page
v-else
:sidebar-items="sidebarItems"
>
<slot
name="page-top"
slot="top"
/>
<slot
name="page-bottom"
slot="bottom"
/>
</Page>
...
複製代碼
在script中對tags變量的判斷數組
export default {
...
data() {
return{
...
tags:false
}
},
...
created(){
this.checkTags()
}
...
checkTags() {
path=this.$route.path
let tags = this.$site.themeConfig.nav.filter(v => v.tags); //判斷tags
if (tags[0].link === path) {
this.tags = true;
this.$page.frontmatter.sidebar = false; //tags不須要側標欄
} else {
this.tags = false;
}
//判斷是不是分類頁面
let type = this.$page.frontmatter.type;
if (type === "classify") {
this.type = "classify";
this.$page.frontmatter.sidebar = false; //tags不須要側標欄
} else {
this.type = "";
}
if (this.$page.frontmatter.defaultHome) {
this.$page.frontmatter.sidebar = false; //主頁不須要側標欄
}
}
}
複製代碼
引入 Tags 組件,其中的 tags 是判斷當前頁面路由 tags 是否爲 true,這是 config.js 中配置的選項。 再新建的 Tags.vue 文件中加入如下內容,這是我定義的tag組件,大家能夠根據個人組件自行修改bash
<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() {
//核心代碼,整合markdown中tags的數目
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;
this.info = this.$site.pages.filter(v => {
let tags = v.frontmatter.tags;
if (tags) {
return tags.some(v => v === tag);
}
});
},
color() {
// 標籤button顏色
let colors = [
"#3498DB",
"#3EAF7C",
"#5CBBF6",
"#f5A28E",
"#f2AC3B",
"#FA6551",
"#C68CE0"
];
return colors[parseInt(Math.random() * colors.length)];
}
},
mounted() {
//當路由?tag='xxx'時能自動跳轉到對應內容
let tag = this.$route.query.tag;
if (tag) {
this.change(tag);
}
}
};
</script>
<style lang='stylus' scoped>
.tag {
max-width: 46.5rem;
margin: 0 auto;
padding: 0 2.5rem;
.items {
margin-bottom: 2rem;
span {
vertical-align: middle;
cursor: pointer;
margin: 0.5rem 0.5rem 0.2rem;
padding: 0.4rem 0.7rem;
display: -webkit-inline-box;
display: -ms-inline-flexbox;
display: inline-flex;
border-radius: 0.2rem;
background: #fff;
color: #fff;
font-size: 1rem;
box-shadow: 0 1px 0.25rem 0 hsla(0, 0%, 57%, 0.21);
transition: all 0.3s;
background-color: red;
&.active {
transform: scale(1.2);
}
&:hover {
transform: scale(1.2);
}
}
}
}
</style>
複製代碼
其中 Article 組件是標籤中顯示文章內容的部分的組件,你們可自行定義組件及樣式,我貼上本身的 Article 組件markdown
<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>我的一些自動的 vs code 配置(Settings.json)</p>
<ul>
<li>VsCode 經常使用插件配置</li>
</ul>-->
<div v-html="tag.excerpt"></div>
</div>
</div>
<div class="details-btn">
<router-link :to="tag.path">
<div data-v-e422eb16 class="v-btn">
<i data-v-e422eb16 class="what"></i>
閱讀全文
</div>
</router-link>
</div>
<div 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: {}, //索引到的數據
tg: ""
}
};
</script>
<style lang="stylus" scoped>
$color = #3eaf7c;
.abstract {
margin-top: 1rem;
width: 100%;
.abstract-item {
margin: 0 auto 1.2rem;
padding: 1rem 1.2rem;
width: 100%;
overflow: hidden;
border-radius: 0.3rem;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition: all 0.3s;
transition: all 0.3s;
-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;
font-size: 1.2rem;
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);
-webkit-transition: 0.3s ease-in-out;
transition: 0.3s ease-in-out;
}
&:hover:after {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
}
}
.details-btn {
text-align: right;
margin: 0.6rem 0;
.v-btn {
display: inline-block;
font-size: 0.8rem;
padding: 0.4rem 0.7rem;
cursor: pointer;
letter-spacing: 0.1em;
-webkit-transition: all 0.3s;
transition: all 0.3s;
background-color: #efefef;
color: #2c3e50;
border-radius: 0.1rem;
line-height: 1.2;
&:hover {
background-color: $color;
color: #fff;
}
}
}
.article-info {
margin-right: 1rem;
line-height: 1.6rem;
margin-right: 1rem;
line-height: 1.6rem;
font-style: normal;
.text-item {
font-weight: 700;
border: 1px $color;
font-style: normal;
margin-left: 0.4rem;
cursor: pointer;
background-color: #f6f6f6;
padding: 0.2rem 0.4rem;
&.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.7rem;
margin-bottom: 0.7rem;
}
}
}
.what {
font-size: 0.8rem;
color: rgb(153, 153, 153);
}
</style>
複製代碼
至此,標籤雲頁面已經完成,效果以下 dom
Page組件是文章顯示的內容組件,若是須要在文章顯示的時候把標籤顯示到文章頭部,就須要改造Page組件。
把默認主題中 components 下的 Page.vue 文件複製到 docs/.vuepress/theme/components 中, 修改其中內容
<slot name="top"/>
<!-- 如下是添加的內容 -->
<section class="tags" v-if="this.$site.themeConfig.tags&&tags&&tags.length>0">
<!-- tags是this.$page.frontmatter.tags,這是經過vuepress編譯markdown文件中的tags生成的標籤數組。 -->
<span class="tagPopup" v-for="tag in tags">
<!-- $site.themeConfig.tags是config.js中配置的tags目錄 -->
<router-link :to="'/'+$site.themeConfig.tags+'/?tag='+tag" class="tag">{{tag}}</router-link>
</span>
</section>
<!-- 以上是添加的內容 -->
<Content/>
複製代碼
修改後效果以下
至此,標籤雲的改造大體完成,這裏貼上我改造好的源碼地址:vuepress-theme-reform
查看效果可來到個人博客