uni-app 不支持全局配置 image 占位符,因编译器与渲染层均不识别如 uni.config.image.placeholder 的配置;CSS 和 Vue 原型注入无效;重写组件会破坏原生优化;可行方案是封装 u-img 组件统一管理 placeholder。

uni-app 没有提供全局配置项来统一设置所有 image 组件的默认占位符,所谓“全局默认”只能靠封装或约定实现,硬改底层行为既不可靠也不推荐。
为什么不能直接配全局 placeholder
image 组件的 placeholder 属性是每个实例单独传入的,uni-app 编译器和原生渲染层都不识别类似 uni.config.image.placeholder 这样的全局配置。试图在 main.js 或 uni.scss 里注入默认值,对组件属性无任何影响。
常见错误尝试包括:
- 在
uni.scss中写image { placeholder: '/static/default.png' }—— CSS 不支持该属性,无效 - 用
Vue.prototype.$imagePlaceholder = '/static/default.png'再在模板里写:placeholder="$imagePlaceholder"—— 模板里仍需手动写,不是“默认” - 重写
image组件并注册为全局组件 —— 会破坏原生image在小程序/APP端的特殊优化(如懒加载、解码控制),且 H5 和小程序行为不一致
真正可行的“伪全局”方案:封装自定义图片组件
新建一个 components/u-img.vue,内部使用原生 image,但把占位逻辑收口:
<template>
<image
:src="src"
:placeholder="effectivePlaceholder"
:mode="mode"
@load="$emit('load', $event)"
@error="handleError"
v-bind="$attrs"
></image>
</template>
<script>
export default {
name: 'u-img',
props: {
src: String,
mode: {
type: String,
default: 'aspectFit'
},
placeholder: {
type: String,
default: '/static/placeholder.png' // ← 所有地方统一从这里改
}
},
data() {
return {
hasError: false
}
},
computed: {
effectivePlaceholder() {
return this.hasError ? '/static/error.png' : this.placeholder
}
},
methods: {
handleError() {
this.hasError = true
this.$emit('error', ...arguments)
}
}
}
</script>
使用时:<u-img :src="url"></u-img>,无需再传 placeholder,默认走 /static/placeholder.png;出错后自动 fallback 到 /static/error.png。
关键点:
- 必须确保
/static/placeholder.png真实存在且体积 ≤5KB,否则它自己加载慢,占位就失效 - 不要在该组件内用
v-if控制显示,否则placeholder渲染会被跳过 - 若需响应式宽高比(如 1:1),仍需在外层容器设固定尺寸或用
padding-bottom技巧,组件内部不处理布局
避免踩坑:别用 v-if/v-show 替代 placeholder
有人想“全局控制”就统一加个 v-if="src",这是最典型的反模式:
-
v-if="src"会让组件在src为空时完全不渲染,placeholder根本没机会出现 - 图片加载完成前,整个
image节点消失,DOM 高度归零,列表滚动时会剧烈抖动 - 切换
src时组件销毁重建,触发额外重绘,反而放大闪烁感
placeholder 的价值就在于:同一个 DOM 节点,只换图不换结构。一旦用 v-if,这个前提就没了。
最容易被忽略的是:你改了占位图路径,但忘了检查它在真机上的加载耗时——哪怕只是 200ms 的延迟,用户也会感知为“先闪白再出图”。务必用真机断网测试 + Performance 面板验证占位图是否真的“秒出”。


















