爱凉拌菜真是太好了

使用Vue搭建博客(四)——自定义滚动条

由于项目是一个单页面应用, 在进行路由push后滚动条不会刷新,也就是说当前页面和上一个页面的滚动条的相对位置一样。

就像这样

点击阅读全文过后, 进入某个文章的详情页面,按道理来讲是应该从头开始阅读的。 然而滚动条却已经滚动了一部分距离了

当然上面的图只是模拟, 并不是真正的单页面应用。不过单页面应用确实存在这个问题,这个问题产生的原因可能是 document 还是原来的 document,单页面跳转路由其实向这个 document 中添加和删除节点而已,导致浏览器认为你仍然在浏览同一个页面。使用移动端访问https://blog.linyqiang.com时就可以看到“两个页面的” document.documentElement.scrollTop / document.documentElement.scrollHeight 是一样的(因为移动版版面没有采用自定义滚动)

鉴于上述情况,可以让页面中的某一个部分实现滚动(overflow:scroll)。不过这样滚动条只能紧贴在某个滚动元素的右边,影响美观,因此自己实现一个滚动条来模拟滚动

自定义的ScrollBar.vue

接下来就是在页面中使用ScrollBar.vue了

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
<section class="article-detail" ref="scroll">
<!--文章正文-->
<article class="typo">
<div class="cover" :style="{backgroundImage: ``}"></div>
<header>
<h2>{{currentArticle && currentArticle.title}}</h2>
<h4>{{currentArticle.time && new Date(currentArticle.time).toLocaleString()}}</h4>
<p class="tag">
<span v-for="(tag, index) in currentArticle.tags">{{tag}}</span>
</p>
</header>
<div v-html="currentArticle && currentArticle.content" class="article-content" ref="content">
</div>
</article>
<!--滚动条-->
<scroll-bar
:scrollHeight="scrollHeight"
:scrollTop="scrollTop"
:clientHeight="clientHeight"
@newScrollTop = 'changeScrollTop'
></scroll-bar>
</section>
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
import ScrollBar from '...'
export default {
data () {
return {
scrollTop: 0,
scrollHeight: 0,
clientHeight: 0,
}
},
computed: {
...mapGetters([
'currentArticle'
])
},
mounted () {
// 重点在这里,onscroll 中改变了this.scrollTop, 而scrollbar中的scrollTop属性也就改变了。 因此在用鼠标滚动的时候,滚动条也会跟着滚动
this.$refs.scroll.onscroll = function (e) {
let { clientHeight, scrollTop, scrollHeight } = e.target || e.srcElement
this.scrollTop = scrollTop
this.clientHeight = clientHeight
this.scrollHeight = scrollHeight
}
},
methods: {
changeScrollTop (newScrollTop) {
// 拖动scroll-bar会emit newScrollTop事件,然后article监听到这个事件,并实时改变滚动部位的scrollTop值
this.scrollTop = newScrollTop
this.$refs.scroll.scrollTop = newScrollTop
}
},
components: {
ScrollBar
}
}