相信每个人都碰到过这种情况:
如果自己辛苦开发的产品,在线上遇到图片丢失等问题,导致图片裂开,会不会很难过?
使用占位图片
为了弥补图片加载失败时的用户体验,我们要使用占位图片。
也就是当想要加载的图片加载失败时,去加载其他图片。
就像这样:
虽然同样是没图片,但在视觉上给人的感受却比图像裂开要好得多。
实现这个需求很简单,img 元素有一个 onerror 事件,图像加载失败时,会触发这个事件。
<img src="/image.png" onerror="callback()" />
我们只需要在 callback 中重新设置它的 src 属性就可以了。
function callback() { this.src = '/placeholder.png' }
处理加载占位图片死循环问题
很多讲解如何处理图片丢失的文章,基本上到这里就结束了。
但我想说的是,这种做法存在隐患。
如果替补图片,也就是 placeholder.png 同时也丢失了,那么它会继续触发 onerror 事件。会出现死循环,最终爆栈,页面崩溃。
所以还需要把 onerror 这个事件清除。
function callback() { this.src = '/placeholder.png' this.onerror = null }
使用 Data URL
优化还没结束。
这时图片还是裂开的状态。
有什么办法可以保证占位图片始终都能被加载出来呢?
当然有办法!
使用 Data URL 协议。
Data URL 协议不同于 HTTP 协议那样可能会出现 404 之类的问题,它是用 base 64 对文件内容进行编码。访问 Data URL,就一定可以获取到内容。
然后我们只需要将 Data URL 作为占位图片就大功告成了!
下面是一个图片转 Data URL 的工具:
不过你可能还存在疑惑,Data URL 的体积并不小,放在 HTML 中会不会影响性能?
确实会,但也要分场景。在这个场景中问题并不大。
这就要对我们的占位图有一定要求了,我们可以使用纯色的矢量图来减少图片体积。
下面是一个可以直接生成纯色占位图片 Data URL 的工具:
其实我们也可以期待 W3C 未来会给 img 标签提供一个 placeholder 属性,来专门处理这类问题。