VUE回到顶部组件,使用requestAnimationFrame

背景

这篇文章是18年就写的了,那时候element-ui还没有回到顶部组件,我就弄了一个,现在官网已经有了。想直接使用的话可以使用官网上的,但是官网的是使用setInterval写的,我就顺便改一下这篇文章,使用requestAnimationFrame弄一个。

开发

1. HTML部分

code:

<template>
	<div title="回到顶部" class="comp-to-top" @click="scrollToTop" v-show="toTopShow">TOP</div>
</template>

2. CSS部分

code:

<style scoped lang="scss">
.comp-to-top {
  background-color: #4aa557;
  position: fixed;
  right: 20px;
  bottom: 30px;
  width: 40px;
  height: 40px;
  border-radius: 20px;
  line-height: 40px;
  text-align: center;
  color: #fff;
  font-weight: 800;
  cursor: pointer;
  transition: 0.3s;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.5);
  opacity: 0.5;
  z-index: 100;
  &:hover {
    opacity: 1;
  }
}
</style>

这也没啥说的,自己觉得好看就行。
现在大概是这个样子:
在这里插入图片描述

3. JavaScript部分

这里是重点了,主要是监听两个事件:

屏幕滚动事件
回到顶部按钮的点击事件

屏幕滚动事件

code:

mounted() {
  window.addEventListener("scroll", this.handleScroll, true);
},
destroyed() {
  window.addEventListener("scroll", this.handleScroll, true);
},

这里有两个注意事项:

注意是将事件绑定在window上,监听整个文档的滚动,也可以绑在document或者document.body上
需要在元素加载之后再监听滚动事件
需要将addEventListener的第三个参数设置为true,即取消冒泡,要不然会绑定不成功

code:

handleScroll() {
  this.dom = document.querySelector(this.scrollDom);
  this.scrollTop = this.dom.scrollTop;
  if (this.scrollTop > 100) {
    this.toTopShow = true;
  } else {
    this.toTopShow = false;
  }
},

这里需要注意的地方是:

  1. 一开始不必将回到顶部按钮显示出来,等用户将页面往下滑动一段距离(100)之后再显示回到顶部按钮,这样更加符合用户的操作习惯
  2. this.scrollDom是使用组件的时候传进来的参数,表示触发滚动的对象
回到顶部按钮的点击事件

code:

scrollToTop() {
 let timer = null;
 let _this = this;
 //动画,使用requestAnimationFrame代替setInterval
 cancelAnimationFrame(timer);
 timer = requestAnimationFrame(function fn() {
   if (_this.scrollTop > 1000) {
     _this.scrollTop -= 1000;
     _this.dom.scrollTop = _this.scrollTop;
     timer = requestAnimationFrame(fn);
   } else if (_this.scrollTop > 100 && _this.scrollTop <= 1000) {
     _this.scrollTop -= 100;
     _this.dom.scrollTop = _this.scrollTop;
     timer = requestAnimationFrame(fn);
   } else if (_this.scrollTop > 10 && _this.scrollTop <= 100) {
     _this.scrollTop -= 10;
     _this.dom.scrollTop = _this.scrollTop;
     timer = requestAnimationFrame(fn);
   } else if (_this.scrollTop > 0 && _this.scrollTop <= 10) {
     _this.scrollTop -= 2;
     _this.dom.scrollTop = _this.scrollTop;
     timer = requestAnimationFrame(fn);
   } else {
     cancelAnimationFrame(timer);
     _this.toTopShow = false;
   }
 });
}

这里需要主要几点:

使用requestAnimationFrame,优点就不必多说了
正常情况下回到顶部的速度是由快变慢的,这样看起来更加符合用户的使用习惯,而且效果也更加好看
将距离顶部的距离划分为四个部分,每个部分的速度都不一样

4. 调用

全部页面调用
  • 操作App.vue
  • 添加JavaScript代码
<script>
import ScrollTop from './components/ScrollTop.vue'
export default {
    components: {
        'scroll-top':ScrollTop,
    }
}
</script>
  • 页面中引用
<scroll-top :scrollDom=".content-container"></scroll-top>

大功告成!

单个页面调用

操作需要调用该组件的页面文件即可,方法同上。

5. 全部代码

<template>
    <div title="回到顶部" class="comp-to-top" @click="scrollToTop" v-show="toTopShow">TOP</div>
</template>

<script>
export default {
  props: {
    scrollDom: {
      type: String,
      default: ".content-container"
    }
  },
  data() {
    return {
      dom: null,
      toTopShow: false,
      scrollTop: ""
    };
  },
  mounted() {
    this.$nextTick(() => {
      window.addEventListener("scroll", this.handleScroll, true);
    });
  },
  destroyed() {
    window.addEventListener("scroll", this.handleScroll, true);
  },
  methods: {
    handleScroll() {
      this.dom = document.querySelector(this.scrollDom);
      this.scrollTop = this.dom.scrollTop;
      if (this.scrollTop > 100) {
        this.toTopShow = true;
      } else {
        this.toTopShow = false;
      }
    },
    scrollToTop() {
      let timer = null;
      let _this = this;
      //动画,使用requestAnimationFrame代替setInterval
      cancelAnimationFrame(timer);
      timer = requestAnimationFrame(function fn() {
        if (_this.scrollTop > 1000) {
          _this.scrollTop -= 1000;
          _this.dom.scrollTop = _this.scrollTop;
          timer = requestAnimationFrame(fn);
        } else if (_this.scrollTop > 100 && _this.scrollTop <= 1000) {
          _this.scrollTop -= 100;
          _this.dom.scrollTop = _this.scrollTop;
          timer = requestAnimationFrame(fn);
        } else if (_this.scrollTop > 10 && _this.scrollTop <= 100) {
          _this.scrollTop -= 10;
          _this.dom.scrollTop = _this.scrollTop;
          timer = requestAnimationFrame(fn);
        } else if (_this.scrollTop > 0 && _this.scrollTop <= 10) {
          _this.scrollTop -= 2;
          _this.dom.scrollTop = _this.scrollTop;
          timer = requestAnimationFrame(fn);
        } else {
          cancelAnimationFrame(timer);
          _this.toTopShow = false;
        }
      });
    }
  }
};
</script>
<style scoped lang="scss">
.comp-to-top {
  background-color: #4aa557;
  position: fixed;
  right: 20px;
  bottom: 30px;
  width: 40px;
  height: 40px;
  border-radius: 20px;
  line-height: 40px;
  text-align: center;
  color: #fff;
  font-weight: 800;
  cursor: pointer;
  transition: 0.3s;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.5);
  opacity: 0.5;
  z-index: 100;
  &:hover {
    opacity: 1;
  }
}
</style>
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值