Native js achieve picture lazy loading (lazyLoad)

A. What is lazy loading?

Lazy loading highlighted a "lazy" word lazy is dragging delay means, so "lazy loading" it means lazy loading, for example, we load a page that long, long, long into our browser viewing area installed high, then the priority is lazy loading loading content viewable area, and so on into the rest of the visible area of ​​the load.

II. Why lazy loading?

Lazy loading is a web performance optimization way, it can greatly enhance the user experience. To say the main culprit picture, the picture has been the impact of web performance, a picture now than a few megabytes is a very frequent thing. If every page on the request to enter all image resources, it may load images and other users had already gone out. So, we need lazy loading, when entering the page, requesting only the visible area of ​​the picture resources.

Summed up on two points:

1. fully loaded words will affect the user experience

2. waste of user traffic, some users do not like reading all fully loaded will spend a lot of traffic.

III. Lazy loading implementation principle?

Because the page is a resource-intensive general picture, so we generally implement lazy loading images are for resources, so the realization of the principle here mainly for the picture.

As we all know, a picture is a <img> tag, which is the main source of the image src attribute. Whether the browser request is initiated by the pro-src attribute depending on whether the decision.

If so, then we will have to src attribute <img> tag to start, and when we do not enter the viewing area, let's not give the <img> tag Fu src attribute this not a browser will not send the request a.

Summary: We know from the start tag <img>, it is more important is to determine the viewing area, which is at the core of the whole article.

IV. Implementation steps and Demo

1. introduce a few lazy loading and associated API

document.documentElement.clientHeight//获取屏幕可视区域的高度 

Explanation of MDN:

Intuitive illustration:

element.offsetTop//获取元素相对于文档顶部的高度


Explanation of MDN:

document.documentElement.scrollTop//获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离

Explanation of MDN:

Through the above three API, we obtained three values: highly visible area, the element relative to its parent element from the top of the container, from the top of the top of the browser window and the container element is the scroll bar to scroll height.

There are some people here may not know how to achieve, we still use map to show you:

We saw this picture, you should be able to come to understand. So we come to a judgment formula:

如果:offsetTop-scroolTop<clientHeight,则图片进入了可视区内,则被请求。

2.代码实现

下面的代码就是根据以上公式实现的:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>图片懒加载</title>
    <style>
        img {
            display: block;
            width: 100%;
            height: 300px;
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
    <img data-src="./images/1.jpg" alt="">
    <img data-src="./images/2.jpg" alt="">
    <img data-src="./images/3.jpg" alt="">
    <img data-src="./images/4.jpg" alt="">
    <img data-src="./images/5.jpg" alt="">
    <img data-src="./images/6.jpg" alt="">
    <img data-src="./images/7.jpg" alt="">
    <img data-src="./images/8.jpg" alt="">
    <img data-src="./images/9.jpg" alt="">
    <img data-src="./images/10.jpg" alt="">
    <img data-src="./images/1.jpg" alt="">
    <img data-src="./images/2.jpg" alt="">
</body>
<script>
        var imgs = document.querySelectorAll('img');

        //offsetTop是元素与offsetParent的距离,循环获取直到页面顶部
        function getTop(e) {
            var T = e.offsetTop;
            while(e = e.offsetParent) {
                T += e.offsetTop;
            }
            return T;
        }

        function lazyLoad(imgs) {
            var H = document.documentElement.clientHeight;//获取可视区域高度
            var S = document.documentElement.scrollTop || document.body.scrollTop;
            for (var i = 0; i < imgs.length; i++) {
                if (H + S > getTop(imgs[i])) {
                    imgs[i].src = imgs[i].getAttribute('data-src');
                }
            }
        }

        window.onload = window.onscroll = function () { //onscroll()在滚动条滚动的时候触发
            lazyLoad(imgs);
        }
</script>
</html>

注意:offsetTop是相对于父元素的,所以上面带吗有一个offsetParent。

五.更加方便快捷的实现方式

1.了解一个API

这种实现方式我们只需要了解一个API就行了:

getBoundingClientRect()//获取元素的大小及位置

MDN上的解释:

从这张图我们可以看出,元素是相对于左上角,而不是什么边距。

2.实现方式

通过上面的实验我们都知道,懒加载的一个重点就是要知道什么时候图片是进入了可视区内,那么就上面这张图而言,我们有什么方法判断图片进入了可视区呢。

其实很简单:

我们先获取图片到可视区顶部的距离,并获取到可视区的高度:

var bound = el.getBoundingClientRect();
var clientHeight = window.innerHeight;//这个和前面获取可视区高度的效果一样,只是兼容性问题

然后我们继续思考,当我们滚动条向下滚动的时候,bound.top值会变得越来越小,也就是图片到可视区顶部的距离也越来越小,所以当bound.top == clientHeight时,说明土片马上就要进入可视区了,只要我们在滚动,图片就会进入可视区,那么就需要请求资源了。也就是说,在bound.top<=clientHeight时,图片是在可视区域内的。

经过上面的思考,我们大致明白了如何实现,那么就来编写我们的代码了吧:

只需要把我们的js代码换成如下即可:

 var imgs = document.querySelectorAll('img');

        //用来判断bound.top<=clientHeight的函数,返回一个bool值
        function isIn(el) {
            var bound = el.getBoundingClientRect();
            var clientHeight = window.innerHeight;
            return bound.top <= clientHeight;
        } 
        //检查图片是否在可视区内,如果不在,则加载
        function check() {
            Array.from(imgs).forEach(function(el){
                if(isIn(el)){
                    loadImg(el);
                }
            })
        }
        function loadImg(el) {
            if(!el.src){
                var source = el.dataset.src;
                el.src = source;
            }
        }
        window.onload = window.onscroll = function () { //onscroll()在滚动条滚动的时候触发
            check();
        }

结束语:到这里,我们的小demo也就基本完成了,虽然还有其他方法,在这里我也就不一一阐述了,有兴趣的可以自行网上学习了解。需要本项目源代码的同学可以移步GitHub:https://github.com/Hacker233/JavaScript

总结:懒加载其实就两个重点,一个是元素到各个边距的距离,二个就是判断元素是否在可视区域内。

 

原文:https://zhuanlan.zhihu.com/p/55311726

Guess you like

Origin www.cnblogs.com/doudouzi/p/12102563.html