持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
1. 点击返回顶部按钮,返回页面顶部
a. 监听页面滚动事件,获取滚动的距离,当该值大于一定值,让返回按钮显示,反之隐藏
window.onscroll = function(){
let distance = document.documentElement.scrollTop || document.body.scrollTop;
if( distance >= 300 ){
backTop.style.display = 'block';
}else{
backTop.style.display = 'none';
}
}
b. 点击返回按钮,通过设置定时器,让滚动距离减小慢慢回到页面顶部。滚动距离减小到0,需要清除定时器
backTop.onclick = function(){
let distance = document.documentElement.scrollTop || document.body.scrollTop;
let timer = setInterval(() => {
distance -= 10;
document.documentElement.scrollTop = document.body.scrollTop = distance;
if(distance <= 0){
clearInterval(timer)
}
});
}
遇到的疑问:为什么需要定义两次滚动距离?
因为不能全局定义滚动距离,页面滚动的时候,滚动距离会实时变化。如果在全局一开始定义,滚动距离始终为0。并且返回按钮点击时,需要获取当前位置滚动过的距离
简单实现返回: 点击返回按钮,执行页面滚动事件并平滑滚动
window.scroll({
top: 0,
behavior: 'smooth'
})
2.实现图片的懒加载
方法一
a. 判断图片元素是不是出现在窗口(视野),为真就加载图片
Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。通过此方法获取图片到视口顶部的距离是否小于视口高度,小于则说明图片出现在窗口;设置图片元素的自定义属性data-src,加载时使用 src 代替 data-src
const images = document.querySelectorAll('img')
function lazy () {
images.forEach((elem) => {
if (elem.getBoundingClientRect().top < document.documentElement.clientHeight) {
if (elem.dataset.src && elem.src == '') {
elem.src = elem.dataset.src
}
}
})
}
lazy()
b. 滚动事件
监听页面滚动事件,执行图片加载方法。(加个节流,提高性能;节流的实现方法可以看下最近写的这篇文章《浅谈函数节流、函数防抖》)
window.addEventListener('scroll', throttle(500, lazy))
方法二
IntersectionObserver API,能够监听元素是否到了当前视口
IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:
callback是可见性变化时的回调函数。事件回调函数的参数是 IntersectionObserverEntry的集合,提供在可见视口的目标元素的一系列值。
option是配置对象(该参数可选)
IntersectionObserverEntry.isIntersecting 返回一个布尔值,为true代表目标元素可见
IntersectionObserverEntry.target:被观察的目标元素,是一个 DOM 节点对象
构造函数的返回值是一个观察器实例,实例的observe方法可以指定观察哪个 DOM 节点。
const io = new IntersectionObserver(callback, option);
// 开始观察
io.observe(document.getElementById('example'));
// 停止观察
io.unobserve(element);
// 关闭观察器
io.disconnect();
使用IntersectionObserver监听图片元素是否可见,为真使用 src 代替 图片的自定义属性data-src
const images = document.querySelectorAll('img')
const observer = new IntersectionObserver((changes) => {
// changes: 目标元素集合
changes.forEach((change) => {
if (change.isIntersecting) {
const img = change.target;
if (img.dataset.src && img.src == "") {
img.src = img.dataset.src
}
observer.unobserve(img);
}
});
});
images.forEach(img => observer.observe(img));