导航
.lazy
类标识,用来识别当前容器图片未被真正加载data-url
上.lazy
标识的)判断每个图片是否出现在屏幕中data-url
真实url设置到图片的 src
属性上data-url
和 .lazy
标识lazy.png
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片懒加载</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="container">
</div>
<!-- 模板 -->
<script type="text/template" id="tpl">
<div class="img-view lazy">
<img src="./lazy.png" alt="{{title}}" data-url="{{url}}">
<p>{{title}}</p>
</div>
</script>
<script src="<https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.min.js>"></script>
<script src="utils.js"></script>
<script src="index.js"></script>
</body>
</html>
utils.js 工具函数
function debounce(fn, delay, triggerNow) {
let timer = null;
return function() {
if (timer) window.clearTimeout(timer);
if (triggerNow) {
let exec = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
if (exec) {
fn.apply(this, arguments);
}
} else {
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
}
}
}
function throttle(fn, delay) {
let canUse = true;
return function() {
if (canUse) {
fn.apply(this, arguments);
canUse = false;
setTimeout(() => {
canUse = true;
}, delay);
}
}
}
index.js 核心实现
;(function() {
let oContainer = document.querySelector('.container'),
photos = [],
tpl = document.getElementById('tpl').innerHTML;
console.log(tpl);
function init() {
// 获取数据
getData(() => {
oContainer.innerHTML = renderList();
imgLazyLoad();
});
// 绑定事件
bindEvent();
}
function bindEvent() {
// 监听页面加载完+滚动事件
// 注意 throttle 节流
window.onload = window.onscroll = throttle(imgLazyLoad, 500);
}
// 判断图片是否需要被加载
function imgLazyLoad() {
// 图片 .img-view 容器默认加上 lazy class 用来表示当前容器中图片需要被加载
var oList = document.querySelectorAll('.img-view.lazy'),
cHeight = document.documentElement.clientHeight,
sTop = document.documentElement.scrollTop || document.body.scrollTop;
console.log("剩余需懒加载图片个数:", oList.length);
oList.forEach(item => {
let img = item.getElementsByTagName('img')[0];
let dataUrl = img.getAttribute('data-url');
// 如果图片 出现在了屏幕内
// 则把真实图片url从属性"data-url"中取出设置到src
// 再删除 "data-url" 属性和 img-view 容器上的 lazy 标识
if (item.offsetTop < cHeight + sTop) {
img.setAttribute('src', dataUrl);
img.removeAttribute('data-url');
item.classList.remove('lazy');
}
});
}
// 获取mock数据
function getData(cb) {
axios.get('<https://jsonplaceholder.typicode.com/photos>').then(res => {
photos = res.data;
cb && cb();
});
}
// 解析模板,绑定数据,生成字符串列表
function renderList() {
let list = '';
photos.forEach(photo => {
list += tpl.replace(/\\{\\{(.*?)\\}\\}/g, (node, key) => {
return {
url: photo.url,
title: photo.title
}[key];
});
});
return list;
}
init();
})();
预加载是在页面加载时提前加载未使用的资源,以缩短后续请求的延迟。它可以在用户需要访问资源时,提供更快的响应时间。
预加载常用于加载下一个页面所需的资源,例如,提前加载下一个页面的图片、脚本、样式表等。这样,当用户导航到下一个页面时,这些资源已经被浏览器缓存,可以立即使用,提升页面的加载速度。
实现预加载的方法也有多种,其中一种常见的方式是使用 <link>
元素的 rel
属性,设置为 "preload"
,并指定要预加载的资源的 URL。例如:
<link rel="preload" href="image.jpg" as="image">
<link rel="preload" href="script.js" as="script">
<link rel="preload" href="style.css" as="style">
以上示例中,通过设置 rel="preload"
和 as
属性来指定要预加载的资源类型,可以是 "image"
、"script"
、"style"
等。浏览器会在页面加载过程中提前加载这些资源,以便在需要时立即使用。
onload
事件<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>预加载</title>
<style>
.container {
width: 300px;
}
</style>
</head>
<body>
<div class="container"></div>
<script>
let oDiv = document.querySelector('.container'),
imgArr = [
"<https://placekitten.com/200/100>",
"<https://placekitten.com/300/200>",
"<https://placekitten.com/400/300>",
"<https://placekitten.com/500/400>",
];
imgArr.forEach(imgSrc => {
let img = new Image();
img.style.width = "100%";
img.src = imgSrc;
img.onload = function() {
oDiv.appendChild(img);
}
});
</script>
</body>
</html>