曾经,我非常羡慕那些人见人爱的人,我也想要变成那样,可是后来我才明白人见人爱也是需要天赋的,后来我开始默默努力,我想,就算我不能让每个人都喜欢我,至少因为我做的努力能得到别人的尊重。

图片加载失败优化处理

第一部分:

   网站运营时间长了之后,或者引入的一些图片的链接失效了等等原因,不可避免的会出现图片加载失败的情况。这样给用户的体验非常不好,并且如果前端开发人员在设置img的css属性不当时,对页面的整体布局也会造成极大的影响。

  比如,一个图片连接失效,即使我们添加了alt属性,让用户知道这是什么图片,但是显然体验也是极为糟糕的,如下所示:

    那么有什么好的方法可以解决这个问题呢? 

  我们可以利用图片的onerror属性,设置如下:

 <img src="'一个错误的链接" onerror="this.src='http://www.bianbiangou.cn/index/ICON2.png'" alt="picture">

  即当连接发生了错误之后,即会触发onerror中的函数,我们就可以来重新设置src的属性值了,比如可以设置为公司、网站的商标等等,效果如下:

     

  但是这种方法会出现这样的一个问题: 如果在onerror中设置的图片连接也是无效的,那么onerror的触发就构成了一个死循环,这样,图片就会一直不停地报错,不停的加载。。。

  为了解决这一问题,我们可以在第二次请求的时候停止请求,即使用jquer的one方法即可,先获取到元素,然后绑定一个方法。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>testError</title>
  <script
  src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
<body>
  <img src="fad"  alt="">
  <script>
    $("img").on('error',function () {
      $(this).attr('src', 'http://www.bianbiangou.cn/index/ICON2.png');
    });
  </script>
</body>
</html>

  如上所示,显然img的src是一个不可用的属性,如果出错了,我们就可以用一个之前准备好的图片连接来替换,但是如果这个也出错了呢? 如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>testError</title>
  <script
  src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
<body>
  <img src="fad"  alt="">
  <script>
    $("img").on('error',function () {
      $(this).attr('src', 'ht.png');
    });
  </script>
</body>
</html>

  那么控制台就会一直报错,如下所示:

 

  这时候就是我们用到 jquery的one方法来解决问题的时候了,如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>testError</title>
  <script
  src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
<body>
  <img src="fad"  alt="">
  <script>
    $("img").one('error',function () {
      $(this).attr('src', 'ht.png');
    });
  </script>
</body>
</html>

  这样即使是我们备用的图片也出错了,也不用担心一直报错的问题了。  

 

 

   上面说的是一般的图片的处理方法,在vue的项目中,我们同样可以使用vue提供的once方法,template内的代码如下:

<div class="item-img">
  <img id="errorImg" v-bind:src="'http://bbg-seller.oss-cn-qingdao.aliyuncs.com/test/gp/p1/' + item.picture" v-on:error.once="dosomething($event)" v-bind:alt="item.name">
</div>

  在methods下我们的代码如下:

     dosomething: function (e) {
        e.currentTarget.src = "http://www.ianbiangou.cn/index/ICON2.png"
      }

  这样就可以保证即使我们使用替换的图片也出错了,也不会一直请求服务器,而只是请求一次。 

   在vue项目中,如果能够使用vue的方式就不要使用jquery,实际上jquery可以实现的vue也能实现,但是对于DOM的处理,一些事件的处理,jquery确实很强。

    但是应当注意这样的一个问题:vue构建的是单页面应用,所以在不同的路由切换时并没有加载整个页面,那么once所导致的问题就是只在第一次进入页面时有效,一旦切换路由再切换回来就不能用了,所以这里使用once还是有问题的,这样,我们尽可能的保证替换的图片的存在,毕竟就这一张图片,总得留下吧~~     于是最终我们还是应该在vue中使用v-on:error=""的形式,这样在不重新加载页面的情况下切换路由也能保证图片的正确替代了。

  当然,这只是最简单的一种解决方法,还有很多的方法值得我们去学习和探索,而这也只是一个开头,我们将由这个例子,对图片的加载等进行更深一步的认识。

 

 

 

第二部分

  img标签的事件:

  • onabort
  • onbeforeunload
  • onblur
  • onclick
  • oncontextmenu
  • ondbclick
  • ondrag
  • ondragend
  • ondragleave
  • ondragover
  • ondragstart
  • onerror
  • onfocus
  • onkeydown
  • onkeypress
  • onkeyup
  • onload
  • onmessage
  • onmousedown
  • onmousemove
  • onmouseover
  • onmouseout
  • onmouseup
  • onmousewhell
  • onresize
  • onscroll
  • onselect
  • onsubmit
  • onunload

 可以看出其中的很多事件都是通用的事件,而针对于图片下面几种事件是比较重要的:

  • onerror  图片加载过程中发生错误而触发
  • onabort  图片加载时用户点击停止加载时触发,通常这里触发一个提示:图片正在加载。
  • onload  图片加载完成之后触发

  

对图片进行监听onerror事件

html

<img src="someimage.png" onerror="imgError(this);" />

 

js

// 原生JS:
function imgError(image){
    // 方案一:隐藏图片
    image.style.display = 'none';
    // 方案二:替换为默认图片
    // document.getElementById("img").setAttribute("src", "images/demo.png");
}
 
// 使用jQuery处理:
function imgError(image){
   // 方案一: 隐藏图片 $(image).hide();
   // 方案二: 替换为默认图片
// $(this).attr("src", "images/demo.png"); }

 

 

 

使用jquery进行监听

// 通常不会再HTML里面内联js,可以使用.error对图片进行监听处理
$('#test img').error(function() {
    $(this).hide();
    // $(this).attr("src", "images/demo.png");
});

 

 

 

 

使用函数处理

// 原生JS解决方案
function $id(id) {
    return !id || id.nodeType === 1 ? id : document.getElementById(id);
}
function isType(o, t) {
    return (typeof o).indexOf(t.charAt(0).toLowerCase()) === 0;
}
 
// 主要逻辑
function image(src, cfg) {
    var img, prop, target;
    cfg = cfg || (isType(src, 'o') ? src : {});
 
    img = $id(src);
    if (img) {
        src = cfg.src || img.src;
    } else {
        img = document.createElement('img');
        src = src || cfg.src;
    }
 
    if (!src) {
        return null;
    }
 
    prop = isType(img.naturalWidth,'u') ? 'width' : 'naturalWidth';
    img.alt = cfg.alt || img.alt;
 
    // Add the image and insert if requested (must be on DOM to load or
    // pull from cache)
    img.src = src;
 
    target = $id(cfg.target);
    if (target) {
        target.insertBefore(img, $id(cfg.insertBefore) || null);
    }
 
    // Loaded?
    if (img.complete) {
        if (img[prop]) {
            if (isType(cfg.success,'f')) {
                cfg.success.call(img);
            }
        } else {
            if (isType(cfg.failure,'f')) {
                cfg.failure.call(img);
            }
        }
    } else {
        if (isType(cfg.success,'f')) {
            img.onload = cfg.success;
        }
        if (isType(cfg.failure,'f')) {
            img.onerror = cfg.failure;
        }
    }
 
    return img;
}

 

 

以上函数有很多用处:

1. 获取图片信息:图片是否可下载,图片宽高

image('img',{
    success : function () { alert(this.width + "-" + this.height); },
    failure : function () { alert('image 404!'); },
});
 
// 验证资源是否下载
image('http://cdn.xuanfengge.com/wp-content/themes/lee2.0/images/banner/banner_2.jpg', {
    success : function () {console.log('sucess')},
    failure : function () {console.log('failure')},
    target : 'myContainerId',
    insertBefore : 'someChildOfmyContainerId'
});

 

 

2. 下载并插入图片

var report = $id('report'),
    callback = {
        success : function () {
            report.innerHTML += '<p>Success - ' + this.src + ' ('+this.offsetWidth+'x'+this.offsetHeight+')</p>';
        },
        failure : function () {
            report.innerHTML += '<p>Failure - ' + this.src + ' ('+this.offsetWidth+'x'+this.offsetHeight+')</p>';
        },
        target : 'target'
    };
 
image('img', callback);
image('http://cdn.xuanfengge.com/wp-content/themes/lee2.0/images/banner/banner_2.jpg', callback);

 

 

 

 

 参考文章: http://www.xuanfengge.com/js-image-loading-and-404.html

http://www.w“two”bc.com/article/170738

  

posted @ 2017-05-22 21:02  Wayne-Zhu  阅读(...)  评论(...编辑  收藏

一分耕耘,一分收获。