likes
comments
collection
share

一文学会图片加载失败时设置兜底图片

作者站长头像
站长
· 阅读数 139

前言

随着网速的不断加快和硬件性能的不断提升,页面中使用各种各样的图片已经很普遍了。现在已经很少能见到图片缓慢加载出来的效果,或是图片加载失败显示系统默认的裂开图片。除非你是在网非常不好的地方。

所以为了用户体验的优化,当一张图片因为各种原因加载失败时。设置一张兜底图片来代替它,会比显示空白或者是系统默认的裂开图要强的多。

图片分类

当下展示图片的方法很多,但是主要就两类:imgbackground-img。以下会针对这两种图片进行分别介绍。

img

img图片元素加载出错,主要是通过默认的onerror事件来捕获,具体可查看MDN的介绍:img

原生使用

直接使用img标签

直接通过this获取到这个元素,然后将其链接变为默认图片链接。

<body>
    <img
        src="https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF"
        alt="这是个风景图"
        onerror="this.src = 'https://t7.baidu.com/it/u=4198287529,2774471735&fm=193&f=GIF'">
</body>

动态插入img标签

动态插入与直接使用相同,也是通过获取img标签然后修改其src属性来完成的。所以有两种方法:

  • 一种是向下面代码一样通过函数声明式使用this获取到;
  • 另一种就是直接使用外面定义的变量img,修改其src属性;
<script>
    const img = document.createElement('img');
    img.src = "https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF";
    img.alt = "这是个风景图";
    img.onerror = function () {
        console.log(this); // <img src="https://t7.baidu.com/it/u=4198287529,2774471735&amp;fm=193&amp;f=GIF">
        this.src = "https://t7.baidu.com/it/u=4198287529,2774471735&fm=193&f=GIF";
    }
    document.body.appendChild(img);
</script>

react使用

react中对dom原始的原生事件都进行了包装,使用的其实是合成事件。所以写法上与原生有很大的不同。

import React, { FC } from "react";
import defaultImg from "./xxx.jpg"; // 服务器上的默认图片,如没有替换成图片链接即可

const Home: FC = () => {
	function imgLoadError(event: React.SyntheticEvent<HTMLImageElement, Event>): void {
        console.log(event); // SyntheticEvent {...}
        console.log(event.currentTarget); // <img src="http://localhost:8080/assets/10b22f71ba237249ac0d.jpg">
        event.currentTarget.src = defaultImg;
        event.currentTarget.onerror = null;
	}

	return <img
        src={"https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF" || defaultImg}
        onError={imgLoadError}
    />;
};

vue使用

import defaultImg from "./xxx.jpg"; // 服务器上的默认图片,如没有替换成图片链接即可

<img :src="https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF"" @error="errorImg($event)" />
   
errorImg (e) {
  e.srcElement.src=defaultImg; // 或者使用e.target.src
  e.srcElement.onerror = null;
},

为什么将onerror设为null

可以注意到在上方的错误事件处理中都为其onerror设置了null。这么做是为了防止在默认图片因为手滑等原因也出现加载错误时形成恶性循环。

background-image

相较于img来说,背景图片就要轻松的多。背景图片加载兜底图是通过css3background-image属性的扩充。使得可以一次性设置多张背景图片,图片展示顺序由设置顺序决定(按照设置顺序从上到下逐层展示)。具体可查看MDN:background-image

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 300px;
            height: 300px;
            border: solid 1px #000;
            background-size: contain;
            background-image: url("https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF"),
                url("https://t7.baidu.com/it/u=4198287529,2774471735&amp;fm=193&amp;f=GIF");
        }
    </style>
</head>
<body>
    <div></div>
</body>

针对img显示的另一种处理手段

上面提到了为img添加默认图片是通过onerror事件来实现的,但是!!!

这样做有一个缺陷就是只有一张裂开的图,并没有显示这张图是什么内容。比起图片本身来说,用户更关心这张图片的内容表示的什么。 —— by 张鑫旭

于是上面说出这句话的大佬给出了他所认为的最佳实践。利用img的特性:

图片加载失败时beforeafter伪类会生效,因此可以通过伪类来为其添加默认图片文字说明

这样原本的img标签就不需要任何改动。

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        img {
            width: 200px;
            height: 200px;
            display: inline-block;
            transform: scale(1);
        }

        // before 负责展示默认的失败图片,这里大神是将裂开的图放到了中间,所以background后面给了两个50%。想要使默认图撑满可以改为100%
        img::before {
            content: '';
            width: 100%;
            height: 100%;
            background: #f5f5f5 url("https://t7.baidu.com/it/u=4198287529,2774471735&amp;fm=193&amp;f=GIF") no-repeat center / 50% 50%;
            position: absolute;
            left: 0;
            top: 0;
            color: transparent;
        }

        // after用来展示上面的说明文字
        img::after {
            content: attr(alt);
            width: 100%;
            background-color: rgba(0, 0, 0, .5);
            color: white;
            position: absolute;
            left: 0;
            bottom: 0;
            font-size: 12px;
            line-height: 2;
            text-align: center;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
    </style>
</head>

<body>
    <img src="https://t17.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF" alt="这是个风景图">
</body>

还能说什么呢,大佬就是大佬!大佬牛逼!!!

最后附上大佬的B站视频链接:图片加载出错样式最佳实践

以上就是图片加载失败时设置兜底图片的全部内容啦!如果看完文章有所收获的话,烦请动动小手点个赞哦~

您的支持就是对我最大的鼓励❤️❤️❤️

转载自:https://juejin.cn/post/7288201213732388904
评论
请登录