JavaScript Small Interview~~JavaScript implements lazy picture loading and solves the problem of too much loading in many ways

Posted by jvquach on Tue, 07 Sep 2021 02:28:34 +0200

Pictures are lazy to load, that is, when scrolling a page, pictures are not loaded when they do not appear in the visible area, but only when they appear in the visible area.

Idea: Through the above paragraph, you need to know to lazy load pictures:

  • Bind Scroll Event
  • Visible Window Height (VH)
  • Picture Element Distance Visible Local Top Distance (EH)
  • How to load pictures

When the VH is larger than the EH, the picture appears in the visible window, and vice versa.

How do I load pictures?We can bind any property for the img tag that is not its property name and use the picture path as its property value, for example:

<img data-src="./img/ec6c60c8c5de6d7fa899807cfa8d46f1.jpeg" alt="">
<img imgUrl="./img/ec6c60c8c5de6d7fa899807cfa8d46f1.jpeg" alt="">
<img aabbc="./img/ec6c60c8c5de6d7fa899807cfa8d46f1.jpeg" alt="">

Yes, here we use

<img data-src="./img/ec6c60c8c5de6d7fa899807cfa8d46f1.jpeg" alt="">

For example:

First you need to get the collection of DOM objects for the img element

let imgs = document.querySelectorAll('img')

Traverse through the img's collection of DOM objects to get each img's DOM object

imgs.forEach(item => {
   // Get and compare the distance to the top of the visible area and the height of the visible area for each img distance
   if (item.getBoundingClientRect().top < window.innerHeight) {
      //    Gets the attribute value whose element attribute is data-src and assigns it to the SRC attribute of the imgDOM instance
       item.setAttribute('src',item.getAttribute('data-src'))
        }
 })

The height of the element from the top of the viewport is obtained by getBoundingClientRect().top of the DOM object, and the height of the viewport is obtained by window.innerHeight.

item.getAttribute('data-src'): Indicates the attribute value to get the data-src attribute of the name on the DOM object.

item.setAttribute(attributeName,attributeValue): Indicates that the attributeValue value is assigned to the attributeName attribute as the attribute value.

At this point we need to bind a scroll event, which is bound to window and triggers whenever a scroll bar scrolls:

  let imgs = document.querySelectorAll('img')
        // Bind scroll events for window s
  window.addEventListener('scroll', (e) => {
     // Traverse through the img's collection of DOM objects to get each img's DOM object
     mgs.forEach(item => {
         // Get and compare the distance to the top of the visible area and the height of the visible area for each img distance
         if (item.getBoundingClientRect().top < window.innerHeight) {
         //Gets the attribute value whose element attribute is data-src and assigns it to the SRC attribute of the imgDOM instance
            item.setAttribute('src',item.getAttribute('data-src'))
         }
    })
})

The problem with this is that each scroll triggers a scroll event, which can cause excessive resource loading and waste resources.

There are three solutions given here.

2. Consider compatibility: use anti-shake or throttling

Here's an example using throttling (anti-shake can do it yourself)

<script>
    // 1 Get the DOM object of the img element
    let imgs = document.querySelectorAll('img')
    // Bind scroll events for window s
    window.addEventListener('scroll', imgLazyLoading())
    function imgLazyLoading() {
        let timer
        return () => {
            if (timer) {
                return;
            }
            timer = setTimeout(() => {
                imgs.forEach(item => {
                    // Get and compare the distance to the top of the visible area and the height of the visible area for each img distance
                    if (item.getBoundingClientRect().top < window.innerHeight) {
                        //    Gets the attribute value whose element attribute is data-src and assigns it to the SRC attribute of the imgDOM instance
                        item.setAttribute('src', item.getAttribute('data-src'))
                    }
                })
                timer = null
            }, 500)
        }
    }
</script>

Throttling or anti-shaking can also cause images to load too much, but this saves browser resources more than not.

3, regardless of compatibility

Use the IntersectionObserver constructor (which is provided by browsers and not supported by some browsers).This is cross-observation possible. What is cross-observation?It is what happens when the target element and the visual window cross-localize, and what happens when no cross-localization occurs.

The IntersectionObserver constructor provides two methods for observing what is performed when the target element intersects and what is not.

observe(DOM node): Observe whether a node crosses

unobserve(DOM node): Cancel observation

Create an instance:

  let observer=new  IntersectionObserver(callBack)

callBack is a callBack function that executes twice, once when the target element intersects the visual window, and once when no intersection occurs (called once when seen, once when invisible)

The callBack callback function receives a parameter that contains an array of information about the DOM node being observed and the state of the observation, where what we need is an array of items in each array:

target: the observed DOM node instance

isIntersecting: Whether or not it is observed, when it is observed, we only need to cancel the observation by unobserve(DOM node).The completion code is:

<!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>
</head>
<style>
    div {
        height: 100vh;
        width: 1000px;
        position: relative;
        top: 50%;
        left: 50%;
        transform: translate(50% 50%);
    }
    img {
        padding-top: 50px;
        margin-bottom: 50px;
        height: 500px;
        width: 500px;
        background-repeat: no-repeat;
        background-size: 100% 100%;
        display: inline-block;
        border-top: 2px solid red;
    }
</style>

<body>
    <div>
        <p>1111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>11111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>11111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>11111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>11111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>1111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>1111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>1111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <img data-src="./img/7ff513a853b6d50887606dc436b1ddff.jpeg" alt="">
        <img data-src="./img/8a728780b5ddd5672eb5bf8a4ce23c86.jpeg" alt="">
        <img data-src="./img/ec6c60c8c5de6d7fa899807cfa8d46f1.jpeg" alt="">
        <img data-src="./img/7ff513a853b6d50887606dc436b1ddff.jpeg" alt="">
        <img data-src="./img/8a728780b5ddd5672eb5bf8a4ce23c86.jpeg" alt="">
        <img data-src="./img/ec6c60c8c5de6d7fa899807cfa8d46f1.jpeg" alt="">
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>1111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>1111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
        <p>3ewrw Van der Sar's electricity and electricity fee of the third party in Shandong Province</p>
        <p>1111111111111111111111111111111111111111111111111111111111111111</p>
        <p>22222222222222222222222222222222222222222222222222222222222222</p>
    </div>
</body>
<script>
    let imgs = document.querySelectorAll('img')
    let  observer=new  IntersectionObserver(callBack)
    imgs.forEach(imgItem=>{
        // Watch node, trigger callback function in new IntersectionObserver (callBack)
        observer.observe(imgItem)
    })
    // IntersectionObserver passes in a parameter to the callback function
    function callBack(observerArray){
        // observerArray: A collection of instances and observational states for each observed element object
        observerArray.forEach(item=>{
             // item: Instance and observation state information of the observed element object
            //  isIntersecting: Is it observed
            if(item.isIntersecting){
                // item.target: Observed instance
                let imgDom=item.target
                imgDom.setAttribute('src', imgDom.getAttribute('data-src'))
                // Cancel observation observed
                observer.unobserve(imgDom)
            }
            console.log(item);
        })
    }
</script>
</html>

(LEARN FROM Technical Egg Teacher)

Looking at this, I'd like to compliment you. It's not easy to write big evenings either ~~~count me as a BallBall player (AQA)

Topics: Javascript html5 Vue.js