美文网首页
懒加载与节流

懒加载与节流

作者: twentyshaw | 来源:发表于2019-08-24 19:16 被阅读0次

    1. 概念

    懒加载也叫延迟加载,指的是在长网页中延迟加载图像,是一种很好优化网页性能的方式。 用户滚动到它们之前,可视区域外的图像不会加载。 这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快。 在某些情况下,它还可以帮助减少服务器负载。

    2. 对图片的配置

    将图片的地址写在 data-src里,而不是src里面,方便我们操作它。并且为图片添加class名“lazyload”,标记出需要懒加载的图片。

    3. 思路

    监听页面的滚动(scroll事件),当页面滚动时遍历图片,判断图片是否在视口内,如果是就加载图片。

    4. 代码

    4.1. 监听浏览器的scroll事件:

    window.addEventListener("scroll",onscroll)

    4.2. 判断img是否处于视口:

    4.3. 加载img

    4.4. 节流

    但此时虽然实现了懒加载,但以上的判断和加载会在滚动的时候不断重复调用。为了避免这种情况发生,需要节流:


    5. 完整代码

    function lazyload(images) {
      //将获取到的图片转成数组,也可以写成: Array.from(images)
      let imgs = [].slice.call(images || document.querySelectorAll('.lazyload'))  
      let onscroll = throttle(function() {
          if (imgs.length === 0) {
            return window.removeEventListener('scroll', onscroll)
          }
          imgs = imgs.filter(img => img.classList.contains('lazyload'))
          imgs.forEach(img => inViewport(img) && loadImage(img))
        }, 300)
      
      window.addEventListener('scroll', onscroll)
      window.dispatchEvent(new Event('scroll'))
    }
    
    function inViewport(img){
        let {top, bottom, left, right} = img.getBoundingClientRect()
        let vpWidth = document.documentElement.clientWidth
        let vpHeight = document.documentElement.clientHeight
        return (
            (top > 0 && top < vpHeight || bottom > 0 && bottom < vpHeight) &&
            (left > 0 && left < vpWidth || right > 0 && right < vpWidth)
        )
    }
    
    function loadImage(img, callback){
        let image = new Image() 
        image.src = img.dataset.src
        image.onload = function(){
            img.src = image.src
            img.classList.remove("lazyload")
            if (typeof callback === "function") callback()
        }
    }
    
    function throttle(func, wait){
        let prev,timer
        return function fn(){
            let curr = Date.now()
            let differ = curr - prev
            if (!prev || differ >= wait) {
                func()
                prev = curr
            }else if(differ < wait){
                clearTimeout(timer)
                timer = setTimeout(func, wait -differ)
            }
        }
    }
    

    6. IntersectionObserver接口

    对图片的是否进入视口的观测(第4.2步),也可以通过IntersectionObserver API来实现:

       let observer = new IntersectionObserver(function(entries) {
          entries.forEach(entry => {
            if (entry.intersectionRatio > 0) {
              loadImage(entry.target, () => {
                observer.unobserve(entry.target)
              })
            }
          })
        }, { threshold: 0.01 })
      
        imgs.forEach(img => observer.observe(img))
    
    

    相关文章

      网友评论

          本文标题:懒加载与节流

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