在项目中,我们常常会遇到图片没有或者图片损坏二需要展示一张默认图片。一般情况下,我们的写法是如下:
<img src="images/logo.png" onerror="this.src='@/assets/vue.svg'"/>
然而,这会带来一个问题,即失败加载的图片也加载不出来时,还会再次调用onerror,从而陷入死循环。
这时我们可以将onerror事件置为空,防止进入死循环
<template>
<div>
<img
src="https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel11.jpeg"
@error="handleError"
/>
</div>
</template>
<script setup lang="ts">
import vueImg from "@/assets/vue.svg";
const handleError = (e: Event) => {
let img = e.target as HTMLImageElement;
img.src = vueImg;
img.onerror = null; //防止进入死循环
};
</script>
<style scoped>
img {
width: 600px;
height: 200px;
}
</style>
采用自定义指令
项目中,图片用到的地方还很多,若向上面那样每个地方都写就会显得很冗余。这个时候我们就想到用自定义指令进行封装。
//defaultImg.ts
import vueImg from "@/assets/vue.svg";
const defaultImg = {
async mounted(el: HTMLImageElement, bind: any) {
const imgUrl = bind.value;
if (imgUrl) {
const isHasImage = await handleImage(imgUrl);
if (isHasImage) {
el.setAttribute("src", imgUrl);
} else {
el.setAttribute("src", vueImg);
}
}
},
};
const handleImage = (imgUrl: string) => {
return new Promise((resolve) => {
let img = new Image();
img.src = imgUrl;
img.onload = () => {
console.dir(img);
//complete 属性可返回浏览器是否已完成对图像的加载。
if (img.complete) {
resolve(true);
}
};
img.onerror = () => {
resolve(false);
};
});
};
export default defaultImg;
页面中使用
<template>
<div>
<img v-for="item in imgList" v-default-img="item" />
</div>
</template>
<script setup lang="ts">
// import vueImg from "@/assets/vue.svg";
const imgList = [
"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel11.jpeg", //错误图片地址
"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg",
"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg",
"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg",
];
</script>
<style scoped>
img {
width: 600px;
height: 200px;
}
</style>
实现效果图