奔跑吧!Hello_world

奔跑吧!Hello_world

众所周知:前端页面上的图片是优化时最重要也是最令人头疼的部分,想我也是花费了几个月的时间才优化到令我满意的一般的程度,,,唉,一言难尽啊!

图片的优化有两种方式: 预加载懒加载

先说说 预加载 :我以前写过关于预加载的博客,但是吧,,,里面很多内容不是让我很满意,因为后期发现有些内容在特定情况下才能显现出作用。
预加载的常用场景:在开发的过程,我们经常会遇到这样的要求,当鼠标hover上去的时候,更改菜单的背景。如果没有进行图片预加载的话,会出现闪烁。那么拥有1px的眼睛的设计师们不会放过你的。为什么会出现这张情况?因为hover的时候,图片才会去加载。
比如下面的:

<script type="text/javascript">
            <!--//--><![CDATA[//><!--
            if (document.images) {
                img1 = new Image();
                img2 = new Image();
                img3 = new Image();
                img4 = new Image();
                img1.src = "img/QQ图片20190521233736.jpg";
                img2.src = "img/Cache_3fa28786e3750c51..jpg";
                img3.src = "img/牌.png";
                img4.src = "img/Cache_46072b3594a9a6b5..jpg";
            }
            //--><!]]>
        </script>

还有这个:

var imgSrcArr=[
   '要预加载的图片路径'(可以多个啊)
];
var imgWrap=[];
function preloadImg(arr) {
    for(var i=0;i<arr.length;i++){
        imgWrap[i]=new Image();
        imgWrap[i].src=arr[i];
    }
}
preloadImg(imgSrcArr);

$(function () {
    preloadImg(imgSrcArr);
})

预加载的经典了,最下面那三行意思是:或者等到文字加载完再加载图片。
我一口老血喷出来,如果这样我要你干嘛???

ajax方式实现预加载:

    $(function(){
        $.get('图片的路径');
    })
    /*
    当然我们也可以写成一个函数,这里我就不演示了
    */

试验了很多场景,发现正如我上面所说,预加载其实更适合如hover变换后的图片加载(解决闪屏问题),在网页刚打开的那个图片环境要求下其实作用真不如懒加载。

思量再三,我决定 “投靠” 懒加载 大军!

何为 “懒加载”?
在图片由于某些原因没有显示出来时,用一个占位符去显示,这是提高用户体验的不错方式,目前,京东等商城网站上就用了此技术。
懒加载的精髓:不要将真正图片放在src中引入,src中放“占位图”!

为什么使用懒加载:
在一个页面中,假设有20张图片,每张为100kb,用户在不点滚动条的时候看到的只有4张,如果这20张图片都设置了真正的src,那么当页面首次加载的时候浏览器会立即请求这20张图片资源,需要2000kb的流量;
但是我们做懒加载只请求用户看到的4张图片的话,浏览器只请求这4张图片资源,需要的流量只有400kb。这种手段可以大大减少首屏时间。

代码展示:

index.html

<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <style>
            body{
                text-align: center;
            }
            .game-detail-logo{
                width: 750px;
                height: 430px;
                text-align: center;
                margin-top:30px;
            }
        </style>
        <img src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4259389730,3152819071&fm=26&gp=0.jpg" class="game-detail-logo lazyLoadImg" picAddress="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4003935283,4035293154&fm=27&gp=0.jpg">
        <img src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4259389730,3152819071&fm=26&gp=0.jpg" class="game-detail-logo lazyLoadImg" picAddress="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1535003204948&di=7f297fc3bd01dcbca58f47c470ae9b9e&imgtype=0&src=http%3A%2F%2Fpic50.nipic.com%2Ffile%2F20141019%2F19104397_104929568000_2.jpg">
        <img src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4259389730,3152819071&fm=26&gp=0.jpg" class="game-detail-logo lazyLoadImg" picAddress="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2390937513,1169699994&fm=27&gp=0.jpg">
        <img src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4259389730,3152819071&fm=26&gp=0.jpg" class="game-detail-logo lazyLoadImg" picAddress="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6169699994&fm=27&gp=0.jpg">
        <img src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4259389730,3152819071&fm=26&gp=0.jpg" class="game-detail-logo lazyLoadImg" picAddress="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3947968217,2342505746&fm=27&gp=0.jpg">
    </body>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>   /*用http方式引入jQuery文件(min指压缩过的)*/
    <script type="text/javascript" src="lazyLoadImg.js"></script>
</html>

如上,在几张图片中,我们将 真正的图片 放在picAddress中,在src中放 占位图
在js中,页面加载完成后,根据scrollTop判断图片是否在用户的视野内,如果在,则将picAddress属性中的值取出存放到src属性中 (在滚动事件中重复判断图片是否进入视野,如果进入,则将picAddress属性中的值取出存放到src属性中)。
lazyLoadImg.js

/*
* @example
* <img src="" class="lazyLoadImg" picAddress="">
* @param src里面写的是占位图或者说兜底图地址(一张默认填充图)
* @param class="lazyLoadImg" 是必须的标识
* @param picAddress里面写的是真正需要懒加载的图片地址
*/
const lazyLoadImg = {
  initConfig() {
    const self = this;
    self.imgObject.srcFlag = 'picAddress'; // 图片地址
    self.imgObject.class = 'lazyLoadImg'; // 惰性加载的图片需要添加的class
    self.imgObject.sensitivity = 40; // 鼠标滚动敏感度,该值越小,惰性越强(加载越少)
    self.imgObject.init();
  },
  imgObject: {
    trigger() {
      const self = this;
      const eventType = (self.isPhone && 'touchend') || 'scroll';
      self.imgListData = $('img.' + self.class + '');
      $(window).trigger(eventType);
    },
    init() {
      var self = this;
      $(window).on('scroll', function() {
        self.isLoadImg();
      });
      self.trigger();
    },
    isLoadImg() {
      const self = this;
      function loadNeedImg(img) { // 判断哪些img元素需要加载
        const windowPageYOffset = window.pageYOffset; // 滚动条距离窗口顶部的偏移量
        const offsetAddInner = window.pageYOffset + window.innerHeight; // window.innerHeight返回窗口的文档显示区的高度
        const imgOffsetTop = img.offset().top; // 当前img元素距离窗口顶部的偏移量
        return (
          imgOffsetTop >= windowPageYOffset && // 确保img元素在窗口内
          imgOffsetTop - self.sensitivity <= offsetAddInner //当前img元素是不是在窗口可见范围内,不可见返回:false
        );
      }
      function loadImg(img, index) {
        const imgUrl = img.attr(self.srcFlag);
        const imgLazy = img.attr('src');
        img.attr('src', imgUrl);
        img[0].onload ||  // 开始向服务器请求加载图片
          ((img[0].onload = function() {
            $(this)
              .removeClass(self.class)
              .removeAttr(self.srcFlag),
            (self.imgListData[index] = null),
            (this.onerror = this.onload = null);
          }),
            (img[0].onerror = function() {
              (this.src = imgLazy),
              $(this)
                .removeClass(self.class)
                .removeAttr(self.srcFlag),
              (self.imgListData[index] = null),
              (this.onerror = this.onload = null);
            }));
      }
      self.imgListData.each(function(index, val) {
        if (!val) return;
        const img = $(val);
        if (!loadNeedImg(img)) return;
        const aa = img.attr(self.srcFlag);
        if (!img.attr(self.srcFlag)) return;// 判断是否有规定的picAddress属性,没有则退出当次循环
        loadImg(img, index);
      });
    },
  },
};
lazyLoadImg.initConfig();

我们可以将网络限速将online设成mid-tier mobile或者low-end mobile更容易看到效果!如下:
前端项目分析:我是如何做图片优化的(预加载和懒加载)-LMLPHP

分析适用场景,选择合适的方式才能将一个网站打造的更完美。项目在很多近期博文中提到过,在此就不赘述,,,

07-11 22:44