第一部分:
網站運營時間長了之后,或者引入的一些圖片的鏈接失效了等等原因,不可避免的會出現圖片加載失敗的情況。這樣給用戶的體驗非常不好,並且如果前端開發人員在設置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