爱凉拌菜真是太好了

使用Vue搭建博客(五)——实现目录功能

一个文章如果没有目录怎么行。实现一级目录的功能并不算很难, 但是要包含二级目录的话就需要写长一点代码了。最终效果就像这样


渲染目录的数据结构实现代码: initCatalog方法

调用initCatalog最终得到的数据结构的形式如下:

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
[
{
$1th: {
el: HTMLElement,
name: name属性值,
tag: 标签名字(h1,h2,h3...),
text: 一级标题内容
}
$2th: [
{
el: HTMLElement,
name: name属性值,
tag: 标签名字(h1,h2,h3...),
text: 二级标题内容
},
{
...
},
...
]
},
{
...
},
{
...
}
...
]

有了目录的数据, 就可以根据进行目录渲染了。

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
//article.vue template
<section class="artilce-detail" ref="scroll">
...
...
...
<!--文章目录-->
<aside class="article-catalog" v-if="catalog.length > 0">
<ul class="catalog" v-show="showCatalog">
<li v-for="(item, index) in catalog" class="cata-level1">
<p class="title-level1 title"
@click="goAnchor(item.$1th.el)"
:name="item.$1th.name"
>{{index + 1 + ' ' + item.$1th.text}}</p>
<div class="cata-level2" v-if="item.$2th.length > 0">
<p class="title-level2 title"
v-for="(item2, index2) in item.$2th"
@click="goAnchor(item2.el)"
:name="item2.name"
>
{{(index + 1) + '.' + (index2 + 1) + ' ' + item2.text}}
</p>
</div>
</li>
</ul>
<menu
:class="['menu', 'iconfont', showCatalog ? 'icon-close' : 'icon-menu']"
@click="toggleCatalog"
ref="catalog"
:style="{backgroundColor: showCatalog ? 'transparent' : 'inherit'}"
>
</menu>
</aside>
</section>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//article.vue script
import { initCatalog } from '../../common/js/dom'
import ScrollBar from '...'
export default {
data () {
return {
scrollTop: 0,
scrollHeight: 0,
clientHeight: 0,
catalog: []
}
},
mounted () {
...
...
...
let el = this.$refs.content || document.getElementByClassName('article-content')[0]
this.catalog = initCatalog(el)
}
...
...
...
}

最后还要实现的一个功能就是——点击目录,页面滚动到目录的相应位置

这里要用到一个smoothScroll方法来实现上面代码中的goAnchor方法

实现方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
...
...
methods: {
...
...
...
goAnchor (el) {
let offsetTop = el.offsetTop
smoothScroll.call(this, {offsetTop}, () => {
console.log('滚动到' + offsetTop)
})
},
...
...
...
}
...
...
...

article.vue比较重要的功能就差不过完毕了, 完整代码可以看这里