
你要记住大雨中为你撑伞的人,
帮你挡住外来之物的人,
黑暗中默默抱紧你的人,
逗你笑的人,
陪你彻夜聊天的人,
坐车来看望你的人,
陪你哭过的人,
在医院陪你的人,
总是以你为重的人。
是这些人组成你生命中一点一滴的温暖,
是这些温暖使你远离阴霾,
是这些温暖使你成为善良的人。
——— 村上春树
说明
最近想在项目中加一个页面滚动回到顶部按钮功能,本来想用Element-ui的 Backtop 回到顶部组件,使用说明如下:
<el-backtop target="target-container"></el-backtop>
其中,target绑定的是需要添加回到顶部按钮的容器对象,一般是整个body容器。
必须要注意的是触发滚动的对象,需要有固定的高度,除此之外还需要把该对象的overflow属性设置成auto/scroll,否则默认的overflow:visible,对该组件不生效!
但是当把对象的overflow属性设成auto/scroll后,发现项目中其他文件中添加的scroll监听事件不生效了,非常的坑爹。
//添加window的scroll事件,使用原生方法
window.addEventListener("scroll", this.setNavPosition);
setNavPosition() {
var nav = document.getElementById("item-nav");
//不同浏览器获取scrollTop的方式不一样
var scroll_height =
document.body.scrollTop || document.documentElement.scrollTop;
if (scroll_height > 65) {
nav.style.top = "20px";
} else {
nav.style.top = 80 - scroll_height + "px";
}
}
获取scrollTop的方式
| 浏览器 | 方法 |
|---|---|
| IE6/7/8 | document.documentElement.scrollTop |
| IE9及以上 | window.pageYOffset / document.documentElement.scrollTop |
| Safari | window.pageYOffset / document.body.scrollTop |
| Firefox | window.pageYOffset / document.documentElement.scrollTop |
| Chrome | document.body.scrollTop |
因为document.body.scrollTop与document.documentElement.scrollTop两者有个特点,就是同时只会有一个值生效。比如document.body.scrollTop能取到值的时候,document.documentElement.scrollTop就会始终为0,反之亦然。所以,如果要得到网页的真正的scrollTop值,可以这样:
var sTop=document.body.scrollTop || document.documentElement.scrollTop;
这两个值总会有一个恒为0,所以不用担心会对真正的scrollTop造成影响。
参考链接:
对scrollTop值获取亲身实践
overflow:visible
当容器对象的overflow为默认值visible时,window的scroll事件可以监听到,且对Chrome浏览器来说,document.body.scrollTop不可以获取到scrollTop值,而document.documentElement.scrollTop可以获取到scrollTop值。
- body的overflow属性未设置

- 可以监听到scroll事件,且document.body.scrollTop获取不到值,但是document.documentElement.scrollTop可以获取到值

overflow:auto/scroll
当容器对象的overflow为auto或者scroll时,window的scroll事件监听不到,且对Chrome浏览器来说,document.body.scrollTop可以获取到scrollTop值,而document.documentElement.scrollTop获取不到。


对于为什么overflow会影响scroll事件监听及scrollTop值的获取,目前还不是很清楚,后面会进行补充。
实现方法
因为添加overflow:auto后,Backtop组件会生效,但是无法监听到scroll事件,所以没有使用Backtop组件,自己实现的代码如下:
<template>
<div id="app">
<router-view v-if="isRouterAlive" />
<div v-bind:class="showTopClass" id="top-bar" @click="toTop()"></div>
</div>
</template>
<script>
export default {
data() {
return {
isRouterAlive: true,
showTopBar: false
};
},
computed: {
showTopClass: function() {
return{
hide: !this.showTopBar,
show: this.showTopBar
}
}
},
methods: {
// 用于同一个组件,参数不同,但又想重新加载的情况
reload() {
this.isRouterAlive = false;
this.$nextTick(() => (this.isRouterAlive = true));
},
toTop() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
window.pageYOffset = 0;
},
scrollMonitor() {
let sTop = document.body.scrollTop||document.documentElement.scrollTop;
if(sTop > 600){
this.showTopBar = true;
}else {
this.showTopBar = false;
}
}
},
mounted() {
window.addEventListener("scroll", this.scrollMonitor);
},
destroyed() {
window.removeEventListener("scroll", this.scrollMonitor);
}
};
</script>
<style>
#top-bar {
position: fixed;
bottom: 30px;
left: calc(50% + 640px);
background-image: url("./assets/images/toTop.png");
width: 46px;
height: 46px;
cursor: pointer;
z-index: 5;
}
#top-bar:hover {
background-image: url("./assets/images/toTop2.png");
}
#item_body + #top-bar {
left: calc(50% + 540px);
}
</style>
在App.vue文件中的mounted周期内添加scroll监听事件,滚动高度超过600px后显示回到顶部按钮,否则隐藏。
封装成Vue指令
直接在APP.vue中写返回顶部功能比较麻烦,于是把它抽取成一个指令,也无需在生命周期内进行监听事件,步骤如下:
- 封装方法
Vue.directive('to-top', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// console.log(el);
el.addEventListener("click",()=>{
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
window.pageYOffset = 0;
});
window.addEventListener("scroll", ()=>{
let sTop = document.body.scrollTop||document.documentElement.scrollTop;
if(sTop > 600){
$("#top-bar").show();
}else {
$("#top-bar").hide();
}
});
}
});
- 使用方法
<div class="hide" id="top-bar" v-to-top></div>