Several implementations of image lazy loading

principle

        When there are many pictures on the page, it takes a lot of time to load the pictures, which consumes a lot of server performance. It not only affects the rendering speed but also wastes bandwidth. In order to solve this problem and improve the user experience, there is a way of lazy loading to alleviate The pressure of the server, that is, the content of the visible area is loaded first , and other parts are loaded after entering the visible area, thereby improving performance.

train of thought

        Pictures are loaded according to src . When the picture does not enter the visible area, do not assign a value to src (or give a small loading image first), and then assign a real value to src after the picture enters the visible area. The real address of the picture can be stored in data-src first .

accomplish

<div>
    <h6>图片懒加载</h6>
    <img data-src="/static/images/login-bg-3.jpg" src="/static/images/login-bg-4.jpg"><br>
    <img data-src="/static/images/login-bg-1.jpg" src="/static/images/login-bg-4.jpg"><br>
    <img data-src="/static/images/login-bg.jpg" src="/static/images/login-bg-4.jpg"><br>
    <img data-src="/static/images/login-bg-3.jpg" src="/static/images/login-bg-4.jpg"><br>
    <img data-src="/static/images/login-bg-old.jpg" src="/static/images/login-bg-4.jpg"<br>
    <img data-src="/static/images/login-bg-1.jpg" src="/static/images/login-bg-4.jpg"><br>
    <img data-src="/static/images/login-bg.jpg" src="/static/images/login-bg-4.jpg"><br>
</div>

wx public account [Programming at 10:30] Reply [Frontend] Join the frontend communication family~~,

More dry harvest and real interview questions ——> Station B [Programmer Rita]~~

1. GetBoundingClientRect API implementation 

  data(){
    return{
      flag: true
    }
  },
  created() {
    //this.lazyLoad();
    this.throttle(this.lazyLoad, 3000)()  //首次进入加载
  },
  mounted() {
    const that = this;
    window.addEventListener('scroll',()=>{
       that.throttle(that.lazyLoad, 2000)()
     //that.lazyLoad()
    })
  },
  methods:{
    //节流优化
    throttle(fn, delay){
      const that = this;
      return function () {
        if (!that.flag) return;
        that.flag = false;  //没执行过就一直是false,会直接return
        setTimeout(() => {
          fn.apply(that, arguments);
          that.flag = true; //setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
        }, delay);
      }
    },
    lazyLoad(){
      let images = document.getElementsByTagName('img')  //不是数组,htmlCollection遍历时要注意
      //加定时器的目的是为了让images能够遍历到
      setTimeout(()=>{
        for(let i =0;i<images.length;i++){
          if(images[i].getBoundingClientRect().top<document.body.clientHeight){   //getBoundingClientRect().top 元素的上边相对浏览器视窗的位置如果小于可视窗口的高度
            images[i].src = images[i].dataset.src;
          }
        }
      },300)
    }
  }

2. Implementation of offsetTop API for elements 

The writing method is basically similar to the first one, and the condition for judging entering the visible area has changed. From the figure below, it can be seen that the judging condition for entering the visible area here is an element e

e.offsetTop < document.body.clientHeight + document.body.scrollTop

insert image description here

3.  Implementation of IntersectionObserver API

IntersectionObserver API, can automatically "observe" whether the element is visible, Chrome 51+ already supported. Since the essence of visible( visible) is that the target element and the viewport create an intersection area, so this API is called 交叉观察器.

created() {
    this.intersectionObserver();
},
methods:{
    intersectionObserver(){
        let images = document.getElementsByTagName('img');
        const observer = new IntersectionObserver((imgs) => {
          console.log('imgs===', imgs)
          // imgs: 目标元素集合
          imgs.forEach((img) => {
            // img.isIntersecting代表目标元素可见,可见的时候给src赋值
            if (img.isIntersecting) {
              const item = img.target
              item.src = item.dataset.src
              observer.unobserve(item);
            }
          })
        })
      //定时器和Array.from的目的是让images可遍历
      setTimeout(()=>{
        Array.from(images).forEach(item => {
          observer.observe(item);
        })
      },300)
    }
}

imgs is printed like this:

isIntersecting means that the target element is visible and can be loaded; target corresponds to the real img in the page.

4.  vue-lazyload plugin implementation

(1) Install the plug-in

npm install vue-lazyload --save-dev

(2) Introduce and use in the main.js file

import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)

(3) Modify the image display method to lazy loading (change: src="xxx"  attribute directly to v-lazy="xxx" )

Guess you like

Origin blog.csdn.net/weixin_44427784/article/details/123660027