Vue 折腾记

来源:互联网 发布:2016淘宝刷不了单 编辑:程序博客网 时间:2024/06/15 14:48

前言

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

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

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

废话不多说,看效果图…


效果图

实现思路

  • 过渡用的是requestAnimationFrame,这货只支持IE10+,所以必须做兼容
  • 滚动视图是window.pageYOffset,这货支持IE9+;
  • 为了让可控性更强,图标采用iconfont,具体瞅代码

你能学到什么?

  • 学到一些页面计算相关的东东
  • 动画API的一些知识
  • Vue封装组件相关知识和生命周期和事件监听销毁相关知识的运用

实现功能

  • 视图默认在350处显示返回顶部的按钮和图标
  • 提示文字和颜色,在图标上下左右的自定义,字段都限制了格式和默认值
  • 图标颜色和形状,大小的自定义,字段都限制了格式和默认值
  • 过渡动效的自定义,用法:scrollIt(0, 1500, 'easeInOutCubic', callback);
    • 返回到视图的point,也就是滚动到哪里
    • 过渡时间(ms级别)
    • 一堆过渡效果,字符串格式,其实就是滚动的计算函数..
    • 当然少不了默认参数了,除了callback
  • 兼容性是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>  <div 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>  </div></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,也就是十来分钟的事情,
思路会了,实现更多的是写法而已,至于性能优化,可以一边写一边考虑,也可以实现后有空再优化.
有更好的实现方案和思路可以往下面留言,谢谢

原创粉丝点击