阅读 3195

页面滚动回到顶部功能实现

  你要记住大雨中为你撑伞的人,
  帮你挡住外来之物的人,
  黑暗中默默抱紧你的人,
  逗你笑的人,
  陪你彻夜聊天的人,
  坐车来看望你的人,
  陪你哭过的人,
  在医院陪你的人,
  总是以你为重的人。
  是这些人组成你生命中一点一滴的温暖,
  是这些温暖使你远离阴霾,
  是这些温暖使你成为善良的人。
    
             ——— 村上春树
复制代码

说明

最近想在项目中加一个页面滚动回到顶部按钮功能,本来想用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造成影响。

参考链接:

  1. 为什么scrollTop设置后一直为0的解释和解决方案
  2. 页面滚动条的一二事

对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>
复制代码
文章分类
前端
文章标签