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>

<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实现一个返回顶部backToTop组件 的全部内容, 来源链接: utcz.com/z/348359.html

回到顶部