JavaScript

超轻量级php框架startmvc

Vue实现一个返回顶部backToTop组件

更新时间:2020-05-26 18:06:01 作者:startmvc
最近在学习VUE。自己就在研究怎么用VUE实现一个组件的封装,今日就算留个笔记前言返回顶

最近在学习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>
 <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,也就是十来分钟的事情,

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

希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

Vue 返回顶部 vue实现返回顶部 vue返回顶部组件