Vue.js 破圖處理
以前破圖都是寫個 onerror,怎麼用了Vue之後就不管用了?
前言
- Vue.js 破圖處理
基本介紹
開發環境
- Vue.js 2.x
參考資料
- (尚無)
常見作法
若剛好公司正處於Vue的導入期,以下是我們常看到的新舊併存的作法
HTML部份
- 直接寫一個<img> 並包含原先舊式的 onerror 事件。
<div class="flex-item img-area">
<img :src="'image/' + VueData.ImgPath" onerror="ImgError(this);" />
</div>
JavaScript部份
- 宣告一個JavaScript的Function,用來處理所有<img> 觸發 onerror 時的補救辦法。
<script type="text/javascript">
//破圖處理
function ImgError(source) {
source.src = "image/nopic.jpg";
source.onerror = "";
return true;
}
</script>
但我們透過Vue,是可以不斷改變顯示路徑的呀...
後續要是圖片路徑變了,我們就沒辦法再觸發onerror事件了...
當然,改寫成 VUE 的 :onerror 也是可以
<img :onerror="Imgerror">
Imgerror : 'this.src="image/nopic.jpg"'
不過以我的習慣來說,既然會常常改變的話,
那應該是在Loading完成的時候,再把圖片換上去,才不會在載入時,在網頁上留下一些空白。
實作
我在這邊的作法是
- 先載入預設圖片(破圖時的預設圖片)
- 確認實際圖片存在並載入完成時,再換上去
HTML部份
- 我們稍候會在JS註冊real-img指令,所以在這邊就可以很簡單的使用v-real-img即可!!!
<div class="flex-item img-area">
<img v-real-img="'image/' + VueData.ImgPath" />
</div>
JavaScript部份
- 註冊一個Vue的指令(my-img),並定義好相關的運作機制(確定圖片載入完成,才換上去)。
- 全域指令的部份,依我個人習慣,我會固定放在JS的最上方。
- 下面let vm = new Vue();部份可以忽略,我只是把完整的程式碼放上來而已。
<script type="text/javascript">
/**********************************************************
* 破圖處理 START
**********************************************************/
//註冊全域指令,用於判斷圖片是否能成功載入
//指令名稱:real-img, 使用則為 v-real-img
Vue.directive('real-img', async function (el, binding) {
let defaultImg = "nopic.jpg"; //預設圖片
let newLoadImg = binding.value; //欲載入的新圖片
if (newLoadImg) {
//await : 等待判斷結果回傳
let exist = await imageIsExist(newLoadImg);
if (exist) {
el.setAttribute('src', newLoadImg);
}
else {
el.setAttribute('src', defaultImg);
}
}
})
//檢測圖片是否存在
let imageIsExist = function(url) {
return new Promise((resolve) => {
var img = new Image();
img.onload = function () {
if (this.complete == true){
resolve(true);
img = null;
}
}
img.onerror = function () {
resolve(false);
img = null;
}
img.src = url;
})
}
/**********************************************************
* 破圖處理 END
**********************************************************/
let vm = new Vue({
el: '#vueapp',
data: {
),
methods: {
}
});//end new Vue
</script>
Written By Felix Hsieh