原理
img 标签 有个 src 属性 当src 不为空的时候 随着img 元素渲染到页面上的时候 会异步的去加载资源 。
我们只需要 将 未出现在可视区 的 img 元素 src 设置为空即可 等它出现在屏幕 我们 再设置其src
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>懒加载</title>
<style>
*{
margin: 0;
}
div {
width: 200px;
height: 200px;
margin: 10px auto;
border: 1px solid black;
}
img {
width: 100%;
height: 80%;
}
</style>
</head>
<body>
<div>
1
<img>
</div>
<div>
2
<img>
</div>
<div>
3
<img>
</div>
<div>
4
<img>
</div>
<div>
5
<img>
</div>
<div>
6
<img>
</div>
<div>
7
<img>
</div>
<div>
8
<img>
</div>
</body>
<script>
let clientHeight = document.documentElement.clientHeight
const imgItems = document.getElementsByTagName('img')
const setSrc = ()=>{
for(let i=0;i<imgItems.length;i++){
let detail = imgItems[i].getBoundingClientRect()
console.log(i+1,'是否在视口',detail.top<clientHeight)
if(detail.top<clientHeight&&!imgItems[i].src){
imgItems[i].src = './4.jpg'
}
}
}
//初次设置src
setSrc()
//防抖
function handle (time=1000){
let timer;
return ()=>{
if(timer) {
clearTimeout(timer)
}
timer = setTimeout(()=>{
setSrc()
},time)
}
}
//监听滑动
window.addEventListener('scroll',handle(1000))
//监听窗口
window.addEventListener('resize',()=>{
clientHeight = document.documentElement.clientHeight
setSrc()
})
</script>
</html>
扩展 使用 vue 插件简单实现一个 v-lazy 指令实现图片懒加载
代码:
<!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>Document</title>
<style>
.img {
display: block;
width: 400px;
height: 400px;
}
</style>
<script src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>姓名:{{name}}</h2>
<h2>年纪:{{age}}</h2>
<br />
<div>
<img class="img" v-for="item in list" :key="item.id" v-lazy="item" />
</div>
</div>
</body>
<script>
const plugin = {
install(Vue) {
function lazy(el, binding) {
const io = new IntersectionObserver((entries, observe) => {
if(entries[0].isIntersecting){
setTimeout(()=>{
el.src = binding.value.data_src
},1000)
//解除绑定
observe.disconnect(el)
io.disconnect()
}
});
io.observe(el);
}
//实现自定义指令
Vue.directive("lazy", {
// 表示dom 已经被挂载到父节点上
inserted: lazy,
});
},
};
Vue.use(plugin);
new Vue({
el: "#root",
data() {
return {
name: "kd",
age: 18,
io: null,
obj: {
a: 12,
b: "属性",
},
list: [
{
id: 1,
data_src: "./img/1.jpg",
},
{
id: 2,
data_src: "./img/1.jpg",
},
{
id: 3,
data_src: "./img/1.jpg",
},
{
id: 4,
data_src: "./img/1.jpg",
},
{
id: 5,
data_src: "./img/1.jpg",
},
{
id: 6,
data_src: "./img/1.jpg",
},
],
};
},
mounted() {},
});
</script>
</html>
总结
相关知识点
h5 api intesectionObserve vue自定义插件 vue自定义指令