昨天做了一个公司的笔试,有一个题目
根据列表数据封装一个图片懒加载的组件并引入使用
1.进入页面在浏览器可视区范围内的图片会进行懒加载。
2.向下滑动,当下面的图片进入窗口可视区范围内,开始加载。
3.增加节流,节流时间为1s,防止滑动时频繁触发事件。
4.当所有图片加载完毕时,移除滚动监听事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<style>
.box {
width: 100%;
align-items: center;
display: flex;
flex-wrap: wrap;
}
.container {
width: 23%;
margin: 1%;
}
.container img {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="example">
<div class="box">
<!-- 在此处补充代码 -->
<div class="container" v-for="(item, index) in content" :key='index'>
<img class="lazy" :src="defaultUrl" :data-src="item.src" alt="loading"/>
</div>
</div>
</div>
<script>
/*
*
* 根据列表数据封装一个图片懒加载的组件并引入使用
1.进入页面在浏览器可视区范围内的图片会进行懒加载。
2.向下滑动,当下面的图片进入窗口可视区范围内,开始加载。
3.增加节流,节流时间为1s,防止滑动时频繁触发事件。
4.当所有图片加载完毕时,移除滚动监听事件。
*
* */
// 在此处补充代码
function isInViewport(ele) {
// 元素顶部 距离 视口左上角 的距离top <= 窗口高度 (反例:元素在屏幕下方的情况)
// 元素底部 距离 视口左上角 的距离bottom > 0 (反例:元素在屏幕上方的情况)
// 元素display样式不为none
const notBelow = ele.getBoundingClientRect().top <= window.innerHeight ? true : false;
const notAbove = ele.getBoundingClientRect().bottom >= 0 ? true : false;
const visable = getComputedStyle(ele).display !== "none" ? true : false;
return notBelow && notAbove && visable ? true : false;
}
function LazyLoad() {
// 这个active是节流throttle所用的标志位,这里用到了闭包知识
let active = false;
const lazyLoad = () => {
// throttle相关:200ms内只会执行一次lazyLoad方法
if (active) return;
active = true;
setTimeout(() => {
// 获取所有class为lazy的img标签,这里由于之前已经把处理过的img标签的class删掉了 所以不会重复查找
let lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
lazyImages.forEach(lazyImage => {
// 判断元素是否进入viewport
if (isInViewport(lazyImage)) {
// <img class="lazy" src="[占位图]" data-src="[真实url地址]" data-srcset="[不同屏幕密度下,不同的url地址]" alt="I'm an image!">
// ele.dataset.* 可以读取自定义属性集合,比如data-*
// img.srcset 属性用于设置不同屏幕密度下,image自动加载不同的图片 比如<img src="image-128.png" srcset="image-256.png 2x" />
lazyImage.src = lazyImage.dataset.src;
// 删除class 防止下次重复查找到改img标签
lazyImage.classList.remove("lazy");
}
// 当全部处理完了,移除监听
if (lazyImages.length === 0) {
document.removeEventListener("scroll", lazyLoad);
window.removeEventListener("resize", lazyLoad);
window.removeEventListener("orientationchange", lazyLoad);
}
})
active = false;
}, 1000);
}
document.addEventListener("scroll", lazyLoad);
document.addEventListener("resize", lazyLoad);
document.addEventListener("orientationchange", lazyLoad);
}
var vm = new Vue({
el: "#example",
data() {
return {
content: [{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img1.jpg", num: "45002"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img2.jpg", num: "368724"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img3.jpg", num: "96487"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img4.jpg", num: "86944"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img5.jpg", num: "43761"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img6.jpg", num: "64937"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img7.jpg", num: "34978"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img8.jpg", num: "64913"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img9.jpg", num: "42567"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img10.jpg", num: "4697"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img11.jpg", num: "64874"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img12.jpg", num: "36972"},
{src: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/img13.jpg", num: "67355"},],
defaultUrl: "https://static.nowcoder.com/ajax/img/vue-Lazyloading/img/loading.jpg"
};
},
created() {
},
methods: {},
mounted: function (){
LazyLoad();
}
});
</script>
</body>
</html>
效果如下:当图片出现在可是窗口中时,先加载默认图片,然后一秒钟之后再加载需要的照片