美文网首页
自定义指令懒加载

自定义指令懒加载

作者: HTAO濤 | 来源:发表于2021-01-04 08:41 被阅读0次

    v-LazyLoad

    背景:在类电商类项目,往往存在大量的图片,如 banner 广告图,菜单导航图,美团等商家列表头图等。图片众多以及图片体积过大往往会影响页面加载速度,造成不良的用户体验,所以进行图片懒加载优化势在必行。

    需求:实现一个图片懒加载指令,只加载浏览器可见区域的图片。

    思路:

    图片懒加载的原理主要是判断当前图片是否到了可视区域这一核心逻辑实现的

    拿到所有的图片 Dom ,遍历每个图片判断当前图片是否到了可视区范围内

    如果到了就设置图片的 src 属性,否则显示默认图片

    图片懒加载有两种方式可以实现,一是绑定 srcoll 事件进行监听,二是使用 IntersectionObserver 判断图片是否到了可视区域,但是有浏览器兼容性问题。

    下面封装一个懒加载指令兼容两种方法,判断浏览器是否支持 IntersectionObserver API,如果支持就使用 IntersectionObserver 实现懒加载,否则则使用 srcoll 事件监听 + 节流的方法实现。

    const LazyLoad = {

      // install方法

      install(Vue, options) {

        const defaultSrc = options.default

        Vue.directive('lazy', {

          bind(el, binding) {

            LazyLoad.init(el, binding.value, defaultSrc)

          },

          inserted(el) {

            if (IntersectionObserver) {

              LazyLoad.observe(el)

            } else {

              LazyLoad.listenerScroll(el)

            }

          },

        })

      },

      // 初始化

      init(el, val, def) {

        el.setAttribute('data-src', val)

        el.setAttribute('src', def)

      },

      // 利用IntersectionObserver监听el

      observe(el) {

        var io = new IntersectionObserver((entries) => {

          const realSrc = el.dataset.src

          if (entries[0].isIntersecting) {

            if (realSrc) {

              el.src = realSrc

              el.removeAttribute('data-src')

            }

          }

        })

        io.observe(el)

      },

      // 监听scroll事件

      listenerScroll(el) {

        const handler = LazyLoad.throttle(LazyLoad.load, 300)

        LazyLoad.load(el)

        window.addEventListener('scroll', () => {

          handler(el)

        })

      },

      // 加载真实图片

      load(el) {

        const windowHeight = document.documentElement.clientHeight

        const elTop = el.getBoundingClientRect().top

        const elBtm = el.getBoundingClientRect().bottom

        const realSrc = el.dataset.src

        if (elTop - windowHeight < 0 && elBtm > 0) {

          if (realSrc) {

            el.src = realSrc

            el.removeAttribute('data-src')

          }

        }

      },

      // 节流

      throttle(fn, delay) {

        let timer

        let prevTime

        return function (...args) {

          const currTime = Date.now()

          const context = this

          if (!prevTime) prevTime = currTime

          clearTimeout(timer)

          if (currTime - prevTime > delay) {

            prevTime = currTime

            fn.apply(context, args)

            clearTimeout(timer)

            return

          }

          timer = setTimeout(function () {

            prevTime = Date.now()

            timer = null

            fn.apply(context, args)

          }, delay)

        }

      },

    }

    export default LazyLoad

    使用,将组件内  标签的 src 换成 v-LazyLoad

    <img v-LazyLoad="xxx.jpg" />

    相关文章

      网友评论

          本文标题:自定义指令懒加载

          本文链接:https://www.haomeiwen.com/subject/jkumoktx.html