concept

Lazy loading is actually lazy loading, that is, loading objects when they are needed.

The need for

I. User churn rate (User experience)

Taking APP as an example, the study found that if the response time of the APP is more than 5s, users are most likely to leave the APP, meaning that if your competitor is one or two seconds faster than you, your customers will leave you.

Second, consumption of bandwidth resources

Imagine a website of the type of e-commerce mall. The home page usually has a lot of pictures. If users visit the home page every time, they will request a large number of pictures, but users will not browse all of them, which will consume a lot of bandwidth/traffic and increase the operation cost accordingly.

Different from route lazy loading

We only consider lazy loading of components, not lazy loading of routes, which are actually packaged with es6’s Import + Webpack

Lazy loading of pre-knowledge

  1. LazyloadTop: The distance to the top of the content for lazily loaded elements.

  2. ClientHeight/offsetHeight: intermediate blue areas for web viewing area, namely the area of our naked eye can see, clientHeight/offsetHeight concrete difference to baidu search.

  3. ScrollTop: The distance between the top of the object and the top of the visible content in the window.

Lazy loading refers to listening for browser scroll events and not performing normal render loading at first through some methods. When lazy loading components are required to enter the view, that is, lazyloadTop<=scrollTop+clientHeight, some loading operations are performed.

IntersectionObserver API

When developing a web page, it is often necessary to know whether an element has entered a “viewport,” or whether the user can see it.

The traditional implementation method is to call the getBoundingClientRect() method of the target element (green block) after listening to the Scroll event to get its coordinates corresponding to the upper left corner of the viewport, and then judge whether it is in the viewport. The disadvantage of this method is that it is easy to cause performance problems due to the intensive occurrence of Scroll events and large amount of computation.

There is a new IntersectionObserver API that can automatically “observe” whether elements are visible, and Chrome 51+ already supports it. Because the nature of visible is that a target element intersects with the viewport, the API is called a “intersecting viewer.” For more attributes and how to use them, see Ruan Yifeng’s blob, which is very well written.

Lazy loading of images

1. Replace SRC with a smaller Base64 image (later it was found that the browser limit could not be parsed, so it was replaced with HTTP image)

Img in the page, if there is no SRC attribute or is not an HTTP link address, the browser will not send a request to download the image. Once SRC is set with JS, the browser will send a request to download the image and display it.

2. Use data-src instead

We want to save it in a property at the beginning, so we can set it later, and we can also save it in state, but there are limitations.

// Core code
// When the image is first loaded onto the page
if(! prevVisible && ! visible){if(isImg(childrenProp)){
        setChildren(React.cloneElement(childrenProp,{src:DEFAULT_URL,datasrc:childrenProp.props.src}))
    } 
// When the image enters the view
}else if(! prevVisible && visible){if(isImg(childrenProp)){
        setChildren(React.cloneElement(prevChildren,{src:prevChildren.props.datasrc}))
    } 
}
Copy the code

Background image lazy loading

The principle is no different from lazy image loading, mainly change the SRC attribute to music style backgroundImage or background attribute.

// Core code
 if(! prevVisible && ! visible){ ...... setChildren(React.cloneElement(childrenProp,{style: {... childrenProp.props.style, [hasAttribute(childrenProp)]:`url(${DEFAULT_URL}) `
                    },
                    datasrc:childrenProp.props.style[hasAttribute(childrenProp)]})
                )}
        // When the image enters the view
        }else if(! prevVisible && visible){ ...... setChildren(React.cloneElement(prevChildren,{style: {... childrenProp.props.style, [hasAttribute(childrenProp)]:prevChildren.props.datasrc }, })) } }Copy the code

Component lazy loading

If the component is not an IMG tag or does not have background-color, the component is automatically judged as lazy loading. If the component is lazy loading, it can be displayed directly when reaching the view.

// Core code
// When the image is first loaded onto the page
        if(! prevVisible && ! visible){ ......// When the image enters the view
        }else if(! prevVisible && visible){if(isImg(childrenProp)){
                ...
            } else if(isBackgroundImg(childrenProp)){ 
                ...
            }else{
                setChildren(childrenProp)
            }
        } 
Copy the code

Open source this component

The package size is only 4KB, the core code is less than 20 lines, it is very simple to read, the code uses a new API and proyFill, does not use the traditional listening scroll + throttling, has been posted on Github.

// The usage mode
npm install -S @parrotjs/react-lazyload

import LazyLoad from '@parrotjs/react-lazyload'

const url = 'https://img2.baidu.com/it/u=881124525, 886726031 & FM = 15 & FMT = auto&gp = 0. JPG';

/ / picture
<LazyLoad>
    <img src={url}/>
</LazyLoad>

// Background image
<LazyLoad>
    <div style={{backgroundImage:url}}/>
</LazyLoad>

// The component automatically recognizes the presence of a background image
<LazyLoad>
    <div style={{background:url}}/>
</LazyLoad>

/ / component
<LazyLoad>
    <div>I am looking at the eloquence will show</div>
</LazyLoad>

Copy the code

API

You’ve only opened the placeholder API so far so that you can provide your own components as placeholders for loading and there will be more apis open in the future

Making the address

The address is here. Welcome to use and star. If you have requirements on the project, you can come forward and I will improve the components.