图片懒加载
记录一次笔试题
实现一个图片懒加载事件
- 使用节流函数,时延1s
- 加载完全部图片时销毁监听事件事件
首先我们先实现一个基础的图片懒加载方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lazy Loading with Throttled Scroll</title>
<style>
img {
display: block;
width: 100%;
height: 300px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<img src="https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B"
alt="">
<div id="app">
<img :id="image.id" v-for="image in images" :data-src="image.src" :key="image.id" :alt="image.alt" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
images: [
{ id: 1, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 2, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 3, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 4, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 5, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 6, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 7, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 8, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 9, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 10, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 11, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 12, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
]
};
},
mounted() {
// 监听滚动事件,并使用loadImages函数作为回调函数
window.addEventListener('scroll', () => {
this.loadImages();
});
// 初始化加载可见的图片
this.$nextTick(() => {
this.loadImages();
})
},
methods: {
// 加载图片
loadImages() {
const windowHeight = window.innerHeight;
const windowWidth = window.innerWidth;
for (let i = 0; i < this.images.length; i++) {
const image = this.images[i];
const imgElement = this.$el.querySelector(`img[id="${image.id}"]`);
const imgRect = imgElement.getBoundingClientRect();
if (imgRect.top < windowHeight && imgRect.left < windowWidth) {
// 图片进入视口,加载真实图片源
imgElement.src = image.src
}
}
}
},
});
</script>
</body>
</html>
第二步,增加节流函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lazy Loading with Throttled Scroll</title>
<style>
img {
display: block;
width: 100%;
height: 300px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<img src="https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B"
alt="">
<div id="app">
<img :id="image.id" v-for="image in images" :data-src="image.src" :key="image.id" :alt="image.alt" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
images: [
{ id: 1, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 2, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 3, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 4, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 5, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 6, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 7, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 8, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 9, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 10, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 11, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 12, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
],
throttledLoadImages: null,
};
},
mounted() {
this.throttledLoadImages = this.throttle(this.loadImages, 1000);
// 监听滚动事件,并使用节流的loadImages函数作为回调函数
window.addEventListener('scroll', () => {
this.throttledLoadImages();
});
// 初始化加载可见的图片
this.$nextTick(() => {
this.loadImages();
})
},
methods: {
// 加载图片
loadImages() {
const windowHeight = window.innerHeight;
const windowWidth = window.innerWidth;
for (let i = 0; i < this.images.length; i++) {
const image = this.images[i];
const imgElement = this.$el.querySelector(`img[id="${image.id}"]`);
const imgRect = imgElement.getBoundingClientRect();
if (imgRect.top < windowHeight && imgRect.left < windowWidth) {
// 图片进入视口,加载真实图片源
imgElement.src = image.src
}
}
},
// 创建节流函数
throttle(func, delay) {
let startTime = 0
return function(...args){
const nowTime = new Date().getTime()
const waitTime = delay - (nowTime - startTime)
if(waitTime <= 0){
func.apply(this, args)
startTime = nowTime
}
}
}
},
});
</script>
</body>
</html>
第三步,添加标志位,表示是否所有图片都已加载完成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lazy Loading with Throttled Scroll</title>
<style>
img {
display: block;
width: 100%;
height: 300px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<img src="https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B"
alt="">
<div id="app">
<img :id="image.id" v-for="image in images" :data-src="image.src" :key="image.id" :alt="image.alt" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
images: [
{ id: 1, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 2, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 3, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 4, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 5, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 6, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 7, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 8, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 9, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 10, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 11, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
{ id: 12, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
],
throttledLoadImages: null,
};
},
mounted() {
// 创建节流的loadImages函数
this.throttledLoadImages = this.throttle(this.loadImages, 1000);
// 监听滚动事件,并使用节流的loadImages函数作为回调函数
window.addEventListener('scroll', () => {
this.throttledLoadImages();
});
// 初始化加载可见的图片
this.$nextTick(() => {
this.loadImages();
})
},
beforeDestroy() {
// 组件销毁前移除滚动事件监听器
// window.removeEventListener('scroll', this.throttledLoadImages);
},
methods: {
// 加载图片
loadImages() {
const windowHeight = window.innerHeight;
const windowWidth = window.innerWidth;
let allImagesLoaded = true; // 添加标志位,表示是否所有图片都已加载完成
for (let i = 0; i < this.images.length; i++) {
const image = this.images[i];
const imgElement = this.$el.querySelector(`img[id="${image.id}"]`);
const imgRect = imgElement.getBoundingClientRect();
if (imgRect.top < windowHeight && imgRect.left < windowWidth && !this.imageLoaded(image)) {
// 图片进入视口,加载真实图片源
image.loaded = true;
imgElement.src = image.src
}
if (!this.imageLoaded(image)) {
allImagesLoaded = false; // 如果存在未加载完成的图片,则将标志位置为false
}
}
if (allImagesLoaded) {
// 如果所有图片都已加载完成,则移除滚动事件监听器
console.log('销毁事件')
window.removeEventListener('scroll', this.throttledLoadImages);
}
},
// 检查图片是否已加载
imageLoaded(image) {
return image.loaded;
},
// 创建节流函数
throttle(func, delay) {
let startTime = 0
return function (...args) {
const nowTime = new Date().getTime();
const waitTime = delay - (nowTime - startTime); // 距离上次执行函数的时间间隔
if (waitTime <= 0) {
func.apply(this, args)
console.log("执行")
startTime = nowTime
}
};
},
},
});
</script>
</body>
</html>


