element ui backTop源码解析-逐行逐析
2024-01-07 19:34:04
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);
// Math.pow(a,b) 用于计算指定值的次方值,此处是a的b次方
// 此处用到的是箭头函数
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);
// 节流 封装一个 函数 将onScroll 包裹一层,限制函数触发的频率
this.container.addEventListener('scroll', this.throttledScrollHandler);
// 滚动容器上绑定滚动事件,onScroll
},
methods: {
init() {
this.container = document;
this.el = document.documentElement;
//document 和 documentElement 的区别
// document 是文档对象
// document.documentElement 是整个文档节点树的根节点元素 即<html>元素
// container 容器 设置为 document
//当前元素的
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;
// 滚动的容器设置为el
}
},
onScroll() {
const scrollTop = this.el.scrollTop;//获取滚动条距离顶部的距离
this.visible = scrollTop >= this.visibilityHeight;//页面滚动距离大于指定高度
},
handleClick(e) {
/*
在触发点击的时候
调用scrollToTop 页面滚动到顶部
并且向父组件发送click事件,给组件模拟原生的click事件,以方便父组件调用的时候有点击事件的逻辑
*/
this.scrollToTop();
// 调用滚动到顶部的函数
this.$emit('click', e);//向父组件发送click事件,给组件模拟原生的click事件,以方便父组件调用的时候有点击事件的逻辑
},
scrollToTop() {
const el = this.el;
const beginTime = Date.now();//Date.now()获取到当前时间的时间戳
const beginValue = el.scrollTop;//scrollTop 容器向上滑动后超出rong'qi
const rAF = window.requestAnimationFrame || (func => setTimeout(func, 16));
// 会把每一帧中的所有dom操作集中起来,在一次重绘或重流中完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率
// 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
// requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销
const frameFunc = () => {
const progress = (Date.now() - beginTime) / 500;
// 计算时间间隔 是否大于 500毫秒
if (progress < 1) {
el.scrollTop = beginValue * (1 - easeInOutCubic(progress));
// scrollTop 值会依次减小
rAF(frameFunc);
} else {
el.scrollTop = 0;
}
// 在指定间隔时间里 递归调用 scrollTop 会逐渐减少,然后直到 progress值为1的时候就直接到顶
};
rAF(frameFunc);
}
},
events: {
//
scroll() {
this.onScroll();
}
},
mounted(){
console.log("this0000",this)
},
beforeDestroy() {
this.container.removeEventListener('scroll', this.throttledScrollHandler);
// 在组件销毁的生命周期里 移除 container 上绑定的scroll事件
}
};
</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();//Date.now()获取到当前时间的时间戳
const beginValue = el.scrollTop;//scrollTop 容器向上滑动后超出rong'qi
const rAF = window.requestAnimationFrame || (func => setTimeout(func, 16));
// 会把每一帧中的所有dom操作集中起来,在一次重绘或重流中完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率
// 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
// requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销
const frameFunc = () => {
const progress = (Date.now() - beginTime) / 500;
// 计算时间间隔 是否大于 500毫秒
if (progress < 1) {
el.scrollTop = beginValue * (1 - easeInOutCubic(progress));
// scrollTop 值会依次减小
rAF(frameFunc);
} else {
el.scrollTop = 0;
}
// 在指定间隔时间里 递归调用 scrollTop 会逐渐减少,然后直到 progress值为1的时候就直接到顶
};
rAF(frameFunc);
}
注意 window.requestAnimationFrame
- 会把每一帧中的所有dom操作集中起来,在一次重绘或重流中完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率
- 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
- requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销
文章来源:https://blog.csdn.net/qq_42389674/article/details/135380576
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!