이미지 src
가 잘못되어 요청에 실패할 경우, img의 onerror
속성을 이용해 에러가 발생한 이미지에만 png
로 고정되어 있는 확장자를 jpg
로 변경해 에러 없이 모든 이미지를 띄울수 있도록 처리했다.
이미지 가져올 수 없는 경우 예시
- src 속성이 비었거나 null 일 경우
- src의 URL이 현재 사용자가 보는 페이지의 URL과 같을 경우
- 지정한 이미지가 손상돼 불러올 수 없을 경우
- 이미지의 메타데이터가 손상돼 원본 크기를 알아낼 수 없고,
<img>
요소의 속성에도 크기를 지정하지 않았을 경우- 사용자 에이전트가 지원하지 않는 이미지 형식
출처 : MDN - <img>
만약 img
태그에 onerror
로 에러 처리를 등록했다면,
이미지를 가져올 수 없는 경우 error
이벤트와 함께 onerror
처리기가 호출된다.
<img src="image.jpg"
onerror="this.src='placeholder.jpg'"
alt="Image"
width="200"
height="200">
이렇게 대체 이미지도 넣어줄 수 있다.
먼저 변수와 메서드를 정의해 주었다.
failedImages
: Set() 객체를 통해 고유하게 index를 관리할 수 있도록 했다.onImgError
: onerror 처리 함수getImageSrc
: 서버로부터 img src를 받아오는 함수data() {
failedImages: new Set(),
},
methods: {
getImageSrc(question, idx) {
let baseUrl = `{url}`;
return this.failedImages.has(idx)
? (baseUrl += `.png`)
: (baseUrl += `.jpg`);
},
onImgError(index) {
this.failedImages.add(index);
this.$forceUpdate();
},
}
그리고, 렌더링 부분에서 (예시에서는 vuetify의 v-img를 사용했다)
@error
로 에러 처리함수를 등록해주고,
인자로 index
를 넘겨 반복문 내에서 에러가 발생한 이미지의 index만 failedImages에 담을수 있도록 처리했다.
<template v-for="(question, idx) in questions">
<v-img
:src="getImageSrc(question, idx)"
@error="onImgError(idx)"
... 생략
/>
</template>
이렇게 처리하면, 위에 정의한 getImageSrc
내부에서
// 생략
return this.failedImages.has(idx) // idx가 failedImages에 존재할 경우
? (baseUrl += `.png`)
: (baseUrl += `.jpg`);
에러가 발생한 이미지의 확장자만 png
에서 jpg
로 바꿔서 렌더링이 가능해진다.
이렇게 onerror 속성을 이용해서 에러나는 이미지 없이 모든 이미지를 띄울 수 있었다. 확장자를 동적으로 변경하는 경우를 제외하고도, default 이미지를 설정할 수 있어 자주 쓰일 것 같다.
끝!