本篇我们来实现文章归档页,关键点还是涉及全局计算属性的运用,同时借助了相关插件api来动态生成归档页并注入页面类型。
# 生成归档页并动态注入页面类型
// docs/.vuepress/theme/plugin/util/index.js
const { path } = require('@vuepress/shared-utils')
module.exports = {
// ...
extendPageData($page) {
if ($page.path === '/archives/') {
return $page.pageType = 'archive';
}
},
additionalPages() {
const pages = [{
path: '/archives/',
frontmatter: {
title: '文档归档'
}
}];
return pages;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 改造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'"/>
<Home v-else />
<SvgSprite/>
</div>
</template>
<script>
import Post from '../components/Post'
import Archive from '../components/Archive'
import Home from '../components/Home'
import SideBar from '../components/SideBar'
import SvgSprite from '../components/SvgSprite.vue'
export default {
name: 'Layout',
components: {
Home,
Archive,
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
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
# 编写Archive模板
// docs/.vuepress/theme/components/Archive.vue
<template>
<div class="theme-main__inner archive">
<ul class="archive__list">
<li class="archive__item" v-for="item of archiveList" :key="item.year">
<h2 class="archive__year">{{item.year}}</h2>
<div class="archive__sub-item" v-for="(subItem, key) of item.list" :key="key">
<div class="archive__leaf-list">
<a class="archive__leaf-item" :href="leafItem.path" v-for="leafItem in subItem" :key="leafItem.key">
<span class="archive__date">{{leafItem.date}}</span>
<span class="archive__title">{{leafItem.title}}</span>
</a>
</div>
</div>
</li>
</ul>
</div>
</template>
<script>
const DATE_MAP = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
export default {
name: 'Archive',
computed: {
archiveList() {
let res = {};
let tmp = [];
let list = this.$site.pages.filter(item => {
return item.pid === 'post';
});
list = list.sort((a,b) => {
let time1 = new Date(a.frontmatter.date);
let time2 = new Date(b.frontmatter.date);
return time2 - time1;
})
list.map(item => {
const date = new Date(item.frontmatter.date)
const year = date.getFullYear();
const month = date.getMonth();
const monthKey = DATE_MAP[month]
const day = `${date.getDate()}`;
res[year] || (res[year] = {});
res[year][monthKey] || (res[year][monthKey] = []);
item.date = `${`${month + 1}`.padStart(2, 0)}-${day.padStart(2, 0)}`;
res[year][monthKey].push(item);
})
for (let [key, item] of Object.entries(res)) {
tmp.push({
year: +key,
list: item
});
}
tmp.sort((a, b) => {
return b.year - a.year;
})
return tmp;
}
}
}
</script>
<style lang="stylus">
.archive
border-radius 6px
padding 2.15rem
&__list
margin 0
padding-left 0
list-style none
border-color inherit
&__item
&:first-child
margin-top -2.15rem
&:last-child
margin-bottom -2.15rem
padding-bottom 6rem
border-color inherit
position relative
padding 2.15rem 0
&__year
margin 0
font-size 1.78571rem
position relative
line-height 2.4em
&__sub-item
display flex
align-items flex-start
&:hover
.archive__month:after
opacity 1
&__month-wrap
display flex
justify-content space-between
align-items flex-start
width 3rem
transform scale3d(.75,.75,1)
transform-origin center top
&__leaf-item
position relative
display flex
padding .5rem 0
padding-left 1.5rem
line-height 2rem
align-items flex-start
&:after
position absolute
content '-'
left 0
width 1.5rem
text-align center
&__date
white-space nowrap
letter-spacing 1px
font-size .85rem
opacity .63
padding-right .5rem
&__title
font-size 1.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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
TIP
vuepress的全局计算属性$site.pages
包含了所有文档页,配合blog插件君的pid
标识,我们就可以筛选出所有博客文章。
运行结果如下: