修改page组件,显示文章标题

更新时间: 2021-02-07 16:28:00

默认主题每篇文档头部不能显示标题以及更新时间。我们来改造一下。

# 分析默认Layout

我们把node-modules中的默认主题的Layouts/Layout.vue复制到本地theme下相同位置分析一下








 
 
 
 
 






 
 
 
 
 








 
 
 
 
 
 
 
 






















































































































<template>
  <div
    class="theme-container"
    :class="pageClasses"
    @touchstart="onTouchStart"
    @touchend="onTouchEnd"
  >
    <!-- 这里是导航栏 -->
    <Navbar
      v-if="shouldShowNavbar"
      @toggle-sidebar="toggleSidebar"
    />

    <div
      class="sidebar-mask"
      @click="toggleSidebar(false)"
    />

    <!-- 这里是侧边栏 -->
    <Sidebar
      :items="sidebarItems"
      @toggle-sidebar="toggleSidebar"
    >
      <template #top>
        <slot name="sidebar-top" />
      </template>
      <template #bottom>
        <slot name="sidebar-bottom" />
      </template>
    </Sidebar>

    <!-- 如果$page.frontmatter.home 为 true 就显示首页 -->
    <Home v-if="$page.frontmatter.home" />

    <!-- 如果$page.frontmatter.home 不为 true 就显示Page页 -->
    <Page
      v-else
      :sidebar-items="sidebarItems"
    >
      <template #top>
        <slot name="page-top" />
      </template>
      <template #bottom>
        <slot name="page-bottom" />
      </template>
    </Page>
  </div>
</template>

<script>
import Home from '@theme/components/Home.vue'
import Navbar from '@theme/components/Navbar.vue'
import Page from '@theme/components/Page.vue'
import Sidebar from '@theme/components/Sidebar.vue'
import { resolveSidebarItems } from '../util'

export default {
  name: 'Layout',

  components: {
    Home,
    Page,
    Sidebar,
    Navbar
  },

  data () {
    return {
      isSidebarOpen: false
    }
  },

  computed: {
    shouldShowNavbar () {
      const { themeConfig } = this.$site
      const { frontmatter } = this.$page
      if (
        frontmatter.navbar === false
        || themeConfig.navbar === false) {
        return false
      }
      return (
        this.$title
        || themeConfig.logo
        || themeConfig.repo
        || themeConfig.nav
        || this.$themeLocaleConfig.nav
      )
    },

    shouldShowSidebar () {
      const { frontmatter } = this.$page
      return (
        !frontmatter.home
        && frontmatter.sidebar !== false
        && this.sidebarItems.length
      )
    },

    sidebarItems () {
      return resolveSidebarItems(
        this.$page,
        this.$page.regularPath,
        this.$site,
        this.$localePath
      )
    },

    pageClasses () {
      const userPageClass = this.$page.frontmatter.pageClass
      return [
        {
          'no-navbar': !this.shouldShowNavbar,
          'sidebar-open': this.isSidebarOpen,
          'no-sidebar': !this.shouldShowSidebar
        },
        userPageClass
      ]
    }
  },

  mounted () {
    this.$router.afterEach(() => {
      this.isSidebarOpen = false
    })
  },

  methods: {
    toggleSidebar (to) {
      this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
      this.$emit('toggle-sidebar', this.isSidebarOpen)
    },

    // side swipe
    onTouchStart (e) {
      this.touchStart = {
        x: e.changedTouches[0].clientX,
        y: e.changedTouches[0].clientY
      }
    },

    onTouchEnd (e) {
      const dx = e.changedTouches[0].clientX - this.touchStart.x
      const dy = e.changedTouches[0].clientY - this.touchStart.y
      if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
        if (dx > 0 && this.touchStart.x <= 80) {
          this.toggleSidebar(true)
        } else {
          this.toggleSidebar(false)
        }
      }
    }
  }
}
</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
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

经分析可知,我们要改的是Page组件。

# 分析Page组件

我们把node-modules中的默认主题的components/Page.vue复制到本地theme下相同位置分析一下





 




























<template>
  <main class="page">
    <slot name="top" />

    <Content class="theme-default-content" />
    <PageEdit />

    <PageNav v-bind="{ sidebarItems }" />

    <slot name="bottom" />
  </main>
</template>

<script>
import PageEdit from '@theme/components/PageEdit.vue'
import PageNav from '@theme/components/PageNav.vue'

export default {
  components: { PageEdit, PageNav },
  props: ['sidebarItems']
}
</script>

<style lang="stylus">
@require '../styles/wrapper.styl'

.page
  padding-bottom 2rem
  display block

</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

<Content />组件为渲染.md文件内容的组件,所以想要显示标题,要在Content组件前面加上标题

# ArticleTitle 组件

新建 theme/components/ArticleTitle.vue,像写vue组件一样的去写这个组件

<template>
    <div class="article-title theme-default-content">
        <h1><span class="circle"></span>{{title}}</h1>
        <div class="lastUpdatedTime" v-if="showTime"><span class="text">更新时间:</span> {{lastUpdated}}</div>
    </div>
</template>

<script>
import {filterDateTime } from '../util'
export default {
    props:{
        showTime:{
            type:Boolean,
            default:true
        }
    },
    computed:{
        lastUpdated () {
            return filterDateTime(this.$frontmatter.date).time || filterDateTime(this.$page.lastUpdated).time
        },
        title(){
            return this.$page.title
        }
    }
}
</script>

<style lang="stylus" scoped>
    .article-title{
        padding-bottom:0;
        h1{
            font-size:1.8rem;
            .circle{
                display:inline-block;
                height:1.2rem;
                vertical-align :bottom;
                border:4px solid $accentColor;
                margin-right:10px;
            }
        }
        .lastUpdatedTime{
            font-size:0.9em;
            .text{
                color lighten($textColor, 25%)
            }
        }
    }
</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

其中,页面的titlethis.$pagetitle属性。更新时间也是类似。

# 在page组件中使用ArticleTitle





 









<template>
  <main class="page">
    <slot name="top" />
    
    <articleTitle v-if="isArticle"></articleTitle>
    <Content class="theme-default-content" />
    <PageEdit />

    <PageNav v-bind="{ sidebarItems }" />

    <slot name="bottom" />
  </main>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13

重启一下项目,就能看到每篇文章都显示出了自己的标题。