backTop 回到顶部 组件简介
基础概念
返回页面顶部的操作按钮
代码
<template>
<div>
<transition name="el-fade-in">
<div
v-if="visible"
@click.stop="handleClick"
:style="{
'right': styleRight,
'bottom': styleBottom
}"
class="el-backtop">
<slot>
<el-icon name="caret-top"></el-icon>
</slot>
</div>
</transition>
</div>
</template>
<script>
import throttle from 'throttle-debounce/throttle';
const cubic = value => Math.pow(value, 3);
const easeInOutCubic = value => value < 0.5
? cubic(value * 2) / 2
: 1 - cubic((1 - value) * 2) / 2;
export default {
name: 'ElBacktop',
props: {
visibilityHeight: {
type: Number,
default: 200
},
target: [String],
right: {
type: Number,
default: 40
},
bottom: {
type: Number,
default: 40
}
},
data() {
return {
el: null,
container: null,
visible: false
};
},
computed: {
styleBottom() {
return `${this.bottom}px`;
},
styleRight() {
return `${this.right}px`;
}
},
mounted() {
this.init();
this.throttledScrollHandler = throttle(300, this.onScroll);
this.container.addEventListener('scroll', this.throttledScrollHandler);
},
methods: {
init() {
this.container = document;
this.el = document.documentElement;
if (this.target) {
this.el = document.querySelector(this.target);
if (!this.el) {
throw new Error(`target is not existed: ${this.target}`);
}
this.container = this.el;
}
},
onScroll() {
const scrollTop = this.el.scrollTop;
this.visible = scrollTop >= this.visibilityHeight;
},
handleClick(e) {
this.scrollToTop();
this.$emit('click', e);
},
scrollToTop() {
const el = this.el;
const beginTime = Date.now();
const beginValue = el.scrollTop;
const rAF = window.requestAnimationFrame || (func => setTimeout(func, 16));
const frameFunc = () => {
const progress = (Date.now() - beginTime) / 500;
if (progress < 1) {
el.scrollTop = beginValue * (1 - easeInOutCubic(progress));
rAF(frameFunc);
} else {
el.scrollTop = 0;
}
};
rAF(frameFunc);
}
},
events: {
scroll() {
this.onScroll();
}
},
mounted(){
console.log("this0000",this)
},
beforeDestroy() {
this.container.removeEventListener('scroll', this.throttledScrollHandler);
}
};
</script>
具体分析
props 参数说明
参数名 | 参数说明 |
---|
visibilityHeight | 页面滚动出去的距离大于此值时才显示组件 visible 为true |
target | 触发滚动的对象 滚动的容器 |
right | 控制显示位置,距离页面右边距 |
bot tom | 控制显示位置,距离页面顶部距离 |
data 参数说明
参数名 | 说明 |
---|
el | 触发滚动的对象 |
container | 滚动的容器 |
visible | 是否可见 页面滚动距离大于指定高 |
computed
- styleBottom 根据传入的bottom拼接成px为单位的字符串
- styleRight 根据传入的 right 拼接成px为单位的字符串
mounted
- 调用初始化事件
- 声明一个节流函数
- 给container元素注册滚动的监听事件
methods
init 初始化函数
- 根据条件判断 给 el 和 container 赋值
onScroll 滚动的函数
- 动态获取到el的scrollTop值
- 格努scrollTop值和visibilityHeight对比,给visible 赋值
handleClick 点击事件
- 在触发点击的时候 调用scrollToTop 页面滚动到顶部
- 并且向父组件发送click事件,给组件模拟原生的click事件,以方便父组件调用的时候有点击事件的逻辑
scrollToTop 滚动到顶部
scrollToTop() {
const el = this.el;
const beginTime = Date.now();
const beginValue = el.scrollTop;
const rAF = window.requestAnimationFrame || (func => setTimeout(func, 16));
const frameFunc = () => {
const progress = (Date.now() - beginTime) / 500;
if (progress < 1) {
el.scrollTop = beginValue * (1 - easeInOutCubic(progress));
rAF(frameFunc);
} else {
el.scrollTop = 0;
}
};
rAF(frameFunc);
}
注意 window.requestAnimationFrame
- 会把每一帧中的所有dom操作集中起来,在一次重绘或重流中完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率
- 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
- requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销