• 技术文章 >web前端 >js教程

    Vue实现返回顶部backToTop的组件

    不言不言2018-06-29 15:40:40原创3629
    本篇文章主要介绍了Vue实现一个返回顶部backToTop组件,可以实现回到顶部效果,具有一定的参考价值,有兴趣的可以了解一下

    最近在学习VUE。自己就在研究怎么用VUE实现一个组件的封装,今日就算留个笔记

    前言

    返回顶部这个功能用jq实现,好容易实现,一个animate配合scrollTo就搞定了

    今天我们来试试vue封装一个原生js实现的返回顶部;
    写起来够呛,借助github,看了别人的gist,稍微封装了下;

    当然不是用scrollTo直接调位那种,没有过渡效果怎么说得过去!!还是捣鼓出来了.

    废话不多说,看效果图…

    效果图

    实现思路

    1. 过渡用的是requestAnimationFrame,这货只支持IE10+,所以必须做兼容

    2. 滚动视图是window.pageYOffset,这货支持IE9+;

    3. 为了让可控性更强,图标采用iconfont,具体瞅代码

    你能学到什么?

    1. 学到一些页面计算相关的东东

    2. 动画API的一些知识

    3. Vue封装组件相关知识和生命周期和事件监听销毁相关知识的运用

    实现功能

    1. 视图默认在350处显示返回顶部的按钮和图标

    2. 提示文字和颜色,在图标上下左右的自定义,字段都限制了格式和默认值

    3. 图标颜色和形状,大小的自定义,字段都限制了格式和默认值

    4. 过渡动效的自定义,用法:scrollIt(0, 1500, 'easeInOutCubic', callback);

      1. 返回到视图的point,也就是滚动到哪里

      2. 过渡时间(ms级别)

      3. 一堆过渡效果,字符串格式,其实就是滚动的计算函数..

      4. 当然少不了默认参数了,除了callback

    5. 兼容性是IE9+,特意开了虚拟机去尝试

    代码

    scrollIt.js –过渡滚动实现

    export function scrollIt(
     destination = 0,
     duration = 200,
     easing = "linear",
     callback
    ) {
     // define timing functions -- 过渡动效
     let easings = {
      // no easing, no acceleration
      linear(t) {
       return t;
      },
      // accelerating from zero velocity
      easeInQuad(t) {
       return t * t;
      },
      // decelerating to zero velocity
      easeOutQuad(t) {
       return t * (2 - t);
      },
      // acceleration until halfway, then deceleration
      easeInOutQuad(t) {
       return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
      },
      // accelerating from zero velocity
      easeInCubic(t) {
       return t * t * t;
      },
      // decelerating to zero velocity
      easeOutCubic(t) {
       return --t * t * t + 1;
      },
      // acceleration until halfway, then deceleration
      easeInOutCubic(t) {
       return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
      },
      // accelerating from zero velocity
      easeInQuart(t) {
       return t * t * t * t;
      },
      // decelerating to zero velocity
      easeOutQuart(t) {
       return 1 - --t * t * t * t;
      },
      // acceleration until halfway, then deceleration
      easeInOutQuart(t) {
       return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
      },
      // accelerating from zero velocity
      easeInQuint(t) {
       return t * t * t * t * t;
      },
      // decelerating to zero velocity
      easeOutQuint(t) {
       return 1 + --t * t * t * t * t;
      },
      // acceleration until halfway, then deceleration
      easeInOutQuint(t) {
       return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
      }
     };
     // requestAnimationFrame()的兼容性封装:先判断是否原生支持各种带前缀的
     //不行的话就采用延时的方案
     (function() {
      var lastTime = 0;
      var vendors = ["ms", "moz", "webkit", "o"];
      for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
       window.requestAnimationFrame =
        window[vendors[x] + "RequestAnimationFrame"];
       window.cancelAnimationFrame =
        window[vendors[x] + "CancelAnimationFrame"] ||
        window[vendors[x] + "CancelRequestAnimationFrame"];
      }
    
      if (!window.requestAnimationFrame)
       window.requestAnimationFrame = function(callback, element) {
        var currTime = new Date().getTime();
        var timeToCall = Math.max(0, 16 - (currTime - lastTime));
        var id = window.setTimeout(function() {
         callback(currTime + timeToCall);
        }, timeToCall);
        lastTime = currTime + timeToCall;
        return id;
       };
    
      if (!window.cancelAnimationFrame)
       window.cancelAnimationFrame = function(id) {
        clearTimeout(id);
       };
     })();
    
     function checkElement() {
      // chrome,safari及一些浏览器对于documentElemnt的计算标准化,reset的作用
      document.documentElement.scrollTop += 1;
      let elm =
       document.documentElement.scrollTop !== 0
        ? document.documentElement
        : document.body;
      document.documentElement.scrollTop -= 1;
      return elm;
     }
    
     let element = checkElement(); 
     let start = element.scrollTop; // 当前滚动距离
     let startTime = Date.now(); // 当前时间
    
     function scroll() { // 滚动的实现
      let now = Date.now();
      let time = Math.min(1, (now - startTime) / duration);
      let timeFunction = easings[easing](time);
      element.scrollTop = timeFunction * (destination - start) + start;
    
      if (element.scrollTop === destination) {
       callback; // 此次执行回调函数
       return;
      }
      window.requestAnimationFrame(scroll);
     }
     scroll();
    }

    backToTop.vue

    <template>
     <p class="back-to-top" @click="backToTop" v-show="showReturnToTop" @mouseenter="show" @mouseleave="hide">
      <i :class="[bttOption.iClass]" :style="{color:bttOption.iColor,'font-size':bttOption.iFontsize}"></i>
      <span class="tips" :class="[bttOption.iPos]" :style="{color:bttOption.textColor}" v-show="showTooltips">{{bttOption.text}}</span>
     </p>
    </template>
    
    <script>
     import { scrollIt } from './scrollIt'; // 引入动画过渡的实现
     export default {
      name: 'back-to-top',
      props: {
       text: { // 文本提示
        type: String,
        default: '返回顶部'
       },
       textColor: { // 文本颜色
        type: String,
        default: '#f00'
       },
       iPos: { // 文本位置
        type: String,
        default: 'right'
       },
       iClass: { // 图标形状
        type: String,
        default: 'fzicon fz-ad-fanhuidingbu1'
       },
       iColor: { // 图标颜色
        type: String,
        default: '#f00'
       },
       iFontsize: { // 图标大小
        type: String,
        default: '32px'
       },
       pageY: { // 默认在哪个视图显示返回按钮
        type: Number,
        default: 400
       },
       transitionName: { // 过渡动画名称
        type: String,
        default: 'linear'
       }
      },
      data: function () {
       return {
        showTooltips: false,
        showReturnToTop: false
       }
      },
      computed: {
       bttOption () {
        return {
         text: this.text,
         textColor: this.textColor,
         iPos: this.iPos,
         iClass: this.iClass,
         iColor: this.iColor,
         iFontsize: this.iFontsize
        }
       }
      },
      methods: {
       show () { // 显示隐藏提示文字
        return this.showTooltips = true;
       },
       hide () {
        return this.showTooltips = false;
       },
       currentPageYOffset () {
        // 判断滚动区域大于多少的时候显示返回顶部的按钮
        window.pageYOffset > this.pageY ? this.showReturnToTop = true : this.showReturnToTop = false;
    
       },
       backToTop () {
        scrollIt(0, 1500, this.transitionName, this.currentPageYOffset);
       }
      },
      created () {
       window.addEventListener('scroll', this.currentPageYOffset);
      },
      beforeDestroy () {
       window.removeEventListener('scroll', this.currentPageYOffset)
      }
     }
    </script>
    
    <style scoped lang="scss">
     .back-to-top {
      position: fixed;
      bottom: 5%;
      right: 100px;
      z-index: 9999;
      cursor: pointer;
      width: auto;
      i {
       font-size: 32px;
       display: inline-block;
       position: relative;
       text-align: center;
       padding: 5px;
       background-color: rgba(234, 231, 231, 0.52);
       border-radius: 5px;
       transition: all 0.3s linear;
       &:hover {
        border-radius: 50%;
        background: #222;
        color: #fff !important;
       }
      }
      .tips {
       display: inline-block;
       position: absolute;
       word-break: normal;
       white-space: nowrap;
       width: auto;
       font-size: 12px;
       color: #fff;
       z-index: -1;
      }
      .left {
       right: 0;
       top: 50%;
       margin-right: 50px;
       transform: translateY(-50%);
      }
      .right {
       left: 0;
       top: 50%;
       margin-left: 50px;
       transform: translateY(-50%);
      }
      .bottom {
       bottom: 0;
       margin-top: 50px;
      }
      .top {
       top: 0;
       margin-bottom: 50px;
      }
     }
    </style>

    总结

    从心血来潮到折腾出来,为了兼顾兼容性和拓展性,好像几个小时了.

    不过实现了.你再搬到其他语言,类似ng4,也就是十来分钟的事情,

    思路会了,实现更多的是写法而已,至于性能优化,可以一边写一边考虑,也可以实现后有空再优化.

    以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

    相关推荐:

    关于VUE-地区选择器(V-Distpicker)组件的使用介绍

    关于vue项目的构建,打包和发布过程的介绍

    以上就是Vue实现返回顶部backToTop的组件的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:关于VUE-地区选择器(V-Distpicker)组件的使用介绍 下一篇:在vue项目创建的后初始化首次使用stylus安装方法的介绍
    Web大前端开发直播班

    相关文章推荐

    • JavaScript对象的构造函数和new操作符(实例详解)• Angular知识点分享:聊聊表单、管道、绑定、指令、通信和周期• 深入聊聊node.js中的EventEmitter• 一文掌握JavaScript对象• Angular项目中怎么使用 SASS 样式
    1/1

    PHP中文网