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 –过渡滚动实现

rush: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; },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; },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; },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 = easingseasing;
element.scrollTop = timeFunction * (destination - start) + start;

if (element.scrollTop === destination) {
callback; // 此次执行回调函数
return;
}
window.requestAnimationFrame(scroll);
}
scroll();
}

backToTop.vue

rush:js;">

<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,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;
}
}

总结

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

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

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

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

相关文章

可以通过min-width属性来设置el-table-column的最小宽度。以...
yarn dev,当文件变动后,会自动重启。 yanr start不会自动重...
ref 用于创建一个对值的响应式引用。这个值可以是原始值(如...
通过修改 getWK005 函数来实现这一点。这里的 query 参数就是...
&lt;el-form-item label=&quot;入库类型&quot; ...
API 变动 样式类名变化: 一些组件的样式类名有所变动,可能需...