preface

OK, guys. The previous article said to use the command mode to achieve lazy loading images. In fact, front-end development for so many years, to achieve lazy picture loading is very simple, with the Vue instructions, 30 lines easily achieve a high reuse OF Vue instructions. Take a look.

v-imgLazy

Here, I use IntersectionObserver API to implement it.

The Observe () method of the IntersectionObserver object adds an element to the target set monitored by the IntersectionObserver object. A listener has a set of thresholds and a root, but can monitor multiple target elements to see changes in the visible area of those target elements.

Simply put, you can listen for DOM elements moving in and out of the viewable area, and you can control specific changes.

See IntersectionObserver API for details

Create a directive to store custom directives

directive/imgLazy.js

// Introduce the default image

import baseImg from '@/assets/logo.png';



let timer = null;

// Create a listener

let observer = new IntersectionObserver((entries) = >{

  "// entries are a collection of all monitored objects

  entries.forEach(entry= >{

    if(entry.isIntersecting || entry.intersectionRatio>0) {

      // Emitted when the monitored element reaches the threshold and no image is loaded.

! entry.target.isLoaded && showImage(entry.target,entry.target.data_src)

    }

  })

})

function showImage(el,imgSrc){

  const img = new Image();

  img.src = imgSrc;

  img.onload = (a)= >{

    el.src = imgSrc;

    el.isLoaded = true;

  }

}

export default {

  Insert and bind are both used here, since IntersectionObserver can be asynchronous, so it is better to use inserted in case of an accident

  The difference between a inserted element and a bind is that while a inserted element is already inserted into the page, you can get the dom element's position directly.

  inserted(el,binding,vnode) {

    clearTimeout(timer)

    // Display the default image during initialization

    el.src = baseImg;

    // Bind the image address to the DOM

    el.data_src = binding.value;

    observer.observe(el)



    // Stop listening when the component is uninstalled

    const vm = vnode.context;

    timer = setTimeout((a)= > {

      vm.$on('hook:beforeDestroy', () = > {

        observer.disconnect();

      })

    }, 20);

  },

  // Image update triggered

  update(el,binding){

    el.isLoaded = false;

    el.data_src = binding.value;

  },

  // Unbind is not good, will be executed multiple times, improve uninstall with component beforeDestroy

  // unbind(){

  // // Stop listening

  // observer.disconnect();

  // }

}

Copy the code

Used in main.js to register global directives

main.js

import imgLazy from '@/directive/imgLazy.js'

Vue.directive('imgLazy', imgLazy)

Copy the code

Define directives for use in the component to register directives for the current component

import imgLazy from '@/directive/imgLazy.js'

export default {

  // ...

  directives: {

    imgLazy: imgLazy,

  },

}

Copy the code

Use in components

<template>

  <div class='container'>

    <div v-for="(item,index) in imgSrc" :key="index" >

      <img v-imgLazy="item" >

    </div>

  </div>

</template>



<script>

import imgLazy from '@/directive/imgLazy.js'

export default {

  directives: {

    imgLazy: imgLazy,

  },

  data(){

    return {

      imgSrc: [

        "Https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1091405991, & FM = 26 & gp = 0. 859863778 JPG".

        "Https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2396395246, & FM = 26 & gp = 0. 715775841 JPG".

        "Https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=224866248, & FM = 26 & gp = 0. 765861809 JPG".

        "Https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2670715487, & FM = 26 & gp = 0. 1547868437 JPG".

        "Https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2988957523, & FM = 26 & gp = 0. 3295751190 JPG".

        "Https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2698110318, & FM = 26 & gp = 0. 782174384 JPG".

        "Https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1102788601, & FM = 26 & gp = 0. 953675482 JPG".

        "Https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1091405991, & FM = 26 & gp = 0. 859863778 JPG".

        "Https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2396395246, & FM = 26 & gp = 0. 715775841 JPG".

        "Https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=224866248, & FM = 26 & gp = 0. 765861809 JPG".

        "Https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2670715487, & FM = 26 & gp = 0. 1547868437 JPG".

        "Https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2988957523, & FM = 26 & gp = 0. 3295751190 JPG".

        "Https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2698110318, & FM = 26 & gp = 0. 782174384 JPG".

        "Https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1102788601, & FM = 26 & gp = 0. 953675482 JPG".

        "Https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2004055534, & FM = 26 & gp = 0. 3969071219 JPG".

      ]

    }

  }

}

</script>



<style lang="scss" scoped>

img{

  width200px;

  height200px;

}

</style>



Copy the code

The specific effects are as follows:

IntersectionObserver compatibility


The compatibility aspect of IntersectionObserver API is basically compatible with all the IntersectionObserver APIS except IE, so if you want to implement lazy loading on IE, you have to calculate every element yourself. I wrote about lazy loading when I introduced mixins in a previous article for reference.

The evil of the IE

Previous articles:

Hand to hand teach you to use Vue command, personally achieve a news mark and motion animation command

How much do you know about Vue mixins? How to implement a lazy image loading function with mixin

The above codes have been consolidated into the Gitee repository