基础业务:图片懒加载

背景

大部分场景下我们对懒加载的定义实际上是对于图片而言的,对于图片进入可视区域之后去请求图片资源的这种情况、这种case实际上就是一个典型的懒加载的case。这些资源虽然是HTML DOM上的,但是这些资源没有进入可视区域之前,这些图片资源并没有由浏览器发出请求去请求这些图片资源,为什么呢?

对于类似电商这种图片很多,页面很长的业务场景下呢,我们希望相关的资源是要进行懒加载的,原因就是首先它能减少无效资源的加载。假如说我们由一张图片,但是用户只看了两页几十张就退出界面了,剩下的绝大部分图片没有进入到用户的可视区域,用户没有去看。这种情况下,我们就没有必要去加载那么多的图片资源的。这些资源对用户访问来说是无效资源,因为他们根本就没看,那么请求这些资源也是无效的请求。

第二点就是浏览器对于某一个host name是有并发度上限的,如果说我们的图片所在的CDN和我们的静态资源所在的CDN是同一个CDN的话,我们图片的加载就会阻塞后续JS的加载。JS大部分情况下都是写在body尾部的,那么img大多数情况下会在JS的上面,如果浏览器在并发请求图片的时候达到并发度的限制的话,会导致浏览器没有办法并发请求到后面的JS相关的资源,从而导致网站JS加载的延后,进而影响网站JS相关逻辑的正常使用

图片什么时候会向服务器或者是CDN去请求资源呢,只有img标签里的src属性被设置之后,浏览器在渲染过程中解析到img下的src属性,就会去请求src资源。所以在真实场景下呢,当图片进入可视区域之后,img的src才会被设置进去,而不是说页面一开始加载的时候,可视区之外的img的src属性就被设置进去。如果已经设置了的话,那么显然图片就会被直接的加载进来,也就不存在懒加载的问题了。

原理

懒加载的实现就是对于没有进入界面可视区域内的图片,img的src并不是这个图片的真正URL,可能是一个1像素的占位符,图片真正的URL被存放在img标签的一个自定义属性上。就先叫data-url吧,因为这个地址没有放到SRC上,所以不会造成img向服务端或者CDN去请求图片资源。当图片通过JS逻辑,可能是监听scroll事件,当scroll事件触发到图片已经进入到界面可视区域内,讲img标签上的data-url属性中的URL地址放置到img的src中,然后src的变化就会触发相关图片的资源请求,这种请求机制是延后的,通过监听scroll事件动态设置src

原生实现

首先,将图片的src属性置空,将图片的URL放置在img的一个自定义属性data-original中。

1272362-20180402140335713-1028384900.png

实现来说大体的思路就是先获取屏幕的高度和img图片距离屏幕顶端的高度,当图片距离顶端的高度小于屏幕的高度时候,将图片中存储图片URL的属性拿出来赋值给src就可以了。

var viewHeight = document.documentElement.clientHeight

function lazyload () {
  var eles = document.querySelectorAll('img[data-original][lazyload]')
  Array.prototype.forEach.call(eles, function (item, index) {
    var rect
    if (item.dataset.original === '')
      return
    rect = item.getBoundingClientRect()

    if (rect.bottom >= 0 && rect.top < viewHeight) {
      !function () {
        var img = new Image() // 必要的!
        img.src = item.dataset.original
        img.onload = function () {
          item.src = img.src
        }
        item.removeAttribute('data-original')
        item.removeAttribute('lazyload')
      }()
    }
  })
}

lazyload()

document.addEventListener('scroll', lazyload)

这里要注意的一个点:就是先要执行一下lazyload,否则首屏的几张图片不触发scroll事件是不会被加载出来的。

有人把代码粘贴过去试了下,发现图片是乱的,也没有出现什么懒加载。

1272362-20180402143606459-2025606641.png

那是因为我们没有给图片设置高度,图片都以特别矮的高度展现,肯定是集中再首屏了,当然不会出现什么懒加载。

加了一下CSS样式。

1272362-20180402144037304-1873036564.png

再次运行看看:

1272362-20180402144905776-728770796.gif

ok效果很明显。

zepto插件

zepto也有插件实现了lazyload:

;(function($) {

  function visible(elem){
    elem = $(elem)
    return !!(elem.width() || elem.height()) && elem.css("display") !== "none"
  }

  $.fn.lazyload = function(threshold, callback) {
    // 兼容参数写法
    if($.type(threshold) === 'object') {
      threshold = threshold.threshold;
    }
    if($.type(threshold) === 'function') {
      callback = threshold;
      threshold = 0;
    }
    var $w = $(window),
        th = threshold || 0,
        retina = window.devicePixelRatio > 1,
        attrib = retina? "data-original-retina" : "data-original",
        images = this,
        loaded;

    this.one("lazyload", function() {
      var source = this.getAttribute(attrib);
      source = source || this.getAttribute("data-original");
      if (source) {
        this.setAttribute("src", source);
        if (typeof callback === "function") callback(this);
      }
    });

    function lazyload() {
      var inview = images.filter(function() {
        var $e = $(this);
        if (!visible($e)) return;

        var wt = $w.scrollTop(),
            wb = wt + $w.height(),
            et = $e.offset().top,
            eb = et + $e.height();

        return eb >= wt - th && et <= wb + th;
      });
      // 触发加载
      loaded = inview.trigger("lazyload");
      // images剔除已加载的元素
      images = images.not(loaded);
    }

    $w.on("scroll.lazyload resize.lazyload lookup.lazyload", lazyload);

    lazyload();

    return this;

  };

})(window.Zepto);

原理和刚才我说的也差不多,多了很多差错处理还有健壮性的代码,总体思路都是一样的。

用法就是先用zepto选择器选择需要进行懒加载的图片,然后执行lazyload方法就可以了,前提是要引入zepto及其懒加载相关的插件。

$('img[data-original][lazyload]').lazyload()

具体的演示就不做了,跟上面的一样。

如果大家在前端其他框架中使用懒加载,也会有其他的一些工具去支持,不过还是要清楚原理的,在前端轮子这么多的时代,只有特别扎实的HTML、CSS、JS底层基础还有深厚的计算机基础才能在前端的大潮中站稳脚步。

转载于:https://www.cnblogs.com/isLiu/p/8693507.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端图片懒加载(Image Lazy Loading)和路由懒加载(Route Lazy Loading)是两种不同的优化技术,用于提高用户体验和网站性能。 1. **图片懒加载**: - 图片懒加载是一种延迟加载策略,当用户滚动到图片所在位置时才加载图片,而不是在页面加载初期就全部加载。这有助于减少初始页面加载时间,尤其是在内容较多或图片数量较大的情况下。 - 常见实现方式包括使用Intersection Observer API(Intersection Observer API是一个浏览器原生API,用于检测元素是否进入视口),或者利用HTML的`<img>`标签的`srcset`和`loading`属性,如`loading="lazy"`。 - 相关问题: 1. 如何使用Intersection Observer API实现懒加载? 2. `srcset`和`loading="lazy"`如何协同工作? 3. 图片懒加载对SEO有影响吗? 2. **路由懒加载**: - 路由懒加载是针对单页应用(SPA)的一种优化,只在用户导航到特定路由时才加载该路由对应的组件或模块,而不是一开始就下载所有可能的页面内容。 - 这通常在服务器端渲染(SSR)、动态导入(Dynamic Import)或路由预加载(Preloading)时使用,比如React的`import()`函数或Vue的`require()`。 - 相关问题: 1. 如何在Vue中实现路由懒加载? 2. SSR和路由懒加载有什么区别? 3. 使用动态导入时如何处理异步依赖? 两者都是前端性能优化的重要手段,可以帮助提高网页的加载速度和用户交互体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值