推荐使用 v-img 自定义指令处理图片加载失败,支持预检url、自动重试2次、安全切换fallback图且防死循环;简单场景可用 @error.once 配合本地导入的占位图。

在 Vue 3 模板中处理图片加载失败,核心是**可靠捕获错误 + 安全替换 + 避免死循环**。直接用 @error 是最轻量的方式,但容易踩坑;更优雅的方案是封装为可复用、带状态管理的自定义指令。
✅ 推荐方式:使用 v-img 自定义指令(兼顾健壮与简洁)
全局注册一个 v-img 指令,自动处理加载失败、重试、fallback,并防止默认图再出错导致死循环:
- 指令内部用
new Image()预检 URL,不直接操作el.src,避免触发二次 error - 首次加载失败后,自动尝试 2 次重试(间隔 300ms),失败后才切到 fallback 图
- fallback 图路径通过
v-img的 binding 值传入,支持本地资源(import)或 CDN 地址 - 指令自动清理定时器和事件监听,组件卸载时无内存泄漏
使用示例:
@@##@@
注册代码(如放在 main.ts):
import defaultAvatar from '@/assets/avatar-placeholder.png'
app.directive('img', {
mounted(el, binding) {
const fallbackSrc = binding.value
let retryCount = 0
const maxRetry = 2
const load = (src: string) => {
if (!src) return
const img = new Image()
img.onload = () => el.src = src
img.onerror = () => {
if (retryCount load(src), 300)
} else if (fallbackSrc) {
el.src = fallbackSrc
}
}
img.src = src
}
load(el.src)
}
})
⚠️ 简单场景:@error.once + 显式 fallback(适合静态/低频图片)
如果项目未引入指令体系,或只是个别图片需要兜底,可用此轻量写法:
- 用
@error.once确保只触发一次,避免 fallback 图也失败引发循环 - fallback 图必须确保存在(建议用
require()或import引入本地资源) - 注意:若
:src初始为null或空字符串,@error不会触发,需提前校验
模板写法:
@@##@@ e.target.src = defaultCover" alt="封面图" />
setup 中定义:
import defaultCover from '@/assets/cover-placeholder.jpg' const defaultCover = ref(defaultCover)
? 补充技巧:结合懒加载与错误处理
对首屏外大量图片,建议叠加懒加载逻辑(如 useIntersectionObserver),并在可见时才开始加载 + 错误处理:
- 初始
src留空或设为占位图,用data-src存真实地址 - 元素进入视口后,把
data-src赋给src,再绑定@error.once - 这样既节省流量,又让错误处理只发生在真正需要展示时
示例结构:
@@##@@ e.target.classList.add('loaded')"
@error.once="e => { e.target.src = defaultImg; e.target.classList.add('failed'); }"
alt=""
/>
不需要过度设计,按场景选:高频/关键图片用指令,临时页面用 @error.once,长列表加懒加载。关键是 fallback 图本身要绝对可靠。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











