amis Avatar 头像组件完全指南:JSON 配置、变量绑定与事件交互
【免费下载链接】amis前端低代码框架,通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis
Avatar 头像组件是 amis 低代码框架中用于展示用户头像、缩略图或文字标识的基础展示型组件。通过一行 JSON 配置即可渲染图片、文字或图标三种形态的头像,并支持从上下文中动态绑定数据、失败降级置换、形状与尺寸定制以及事件派发,适用于用户列表、评论模块、个人信息页等场景。读完本文,你将掌握 Avatar 组件的全部属性用法、源码级渲染机制与事件动作配置方案。
组件定位与适用场景
在 amis 中,Avatar 是一个基础展示组件(type: 'avatar'),在官方文档 components/avatar.md 中被定义用来显示用户头像。从源码看,amis 将 Avatar 拆分为两层实现:
- 渲染器层:packages/amis/src/renderers/Avatar.tsx,负责 JSON Schema 解析、变量解析(
resolveVariableAndFilter)与事件派发(dispatchEvent); - 基础组件层:packages/amis-ui/src/components/Avatar.tsx,负责 DOM 结构、图片加载失败处理与 gap 自适应缩放。
因此它既可以在普通页面中使用,也可以作为其他展示类组件(如 Card)的内嵌元素出现。在 amis-editor 插件 中,它被登记为布局场景(static scene = ['layout'])的基础组件,支持在可视化编辑器中通过「属性 / 外观 / 事件」三个面板直接拖拽配置。
基本使用:一行 JSON 显示图片头像
最简单的用法是直接通过src指定图片地址:
{ "type": "avatar", "src": "https://suda.cdn.bcebos.com/amis/images/alice-macaw.jpg" }渲染器会将src交给 amis-ui 的<img>标签输出。这里有一个细节值得注意:渲染器在传值前执行了src = src || defaultAvatar(见 Avatar.tsx),也就是说当src为空时会自动回退到defaultAvatar占位图,这是defaultAvatar属性的实际生效位置。
文字与图标:无图场景的替代方案
当没有图片地址时,可以用文字或图标填充头像:
{ "type": "avatar", "text": "AM" }{ "type": "avatar", "icon": "fa fa-user" }icon的默认值是'fa fa-user'(在 Avatar.tsx 的AvatarField.render中通过默认参数注入),这意味着即使不配置任何内容,组件也会渲染一个默认用户图标。
优先级规则:当src、text、icon同时存在时,依次按src→text→icon的优先级渲染。这一规则在渲染器的render分支中实现(见 amis-ui/src/components/Avatar.tsx):优先走img分支,其次走文字span分支,最后才渲染<Icon>。换句话说,text的优先级永远高于icon,这点在下文的降级置换场景中同样成立。
动态图片与文字:从上下文变量取值
src、text、icon三个属性都支持 amis 变量语法,可从当前数据域中动态取值。渲染器在渲染前会依次调用isPureVariable判断并用resolveVariableAndFilter解析(见 Avatar.tsx)。
{ "data": { "myAvatar": "https://suda.cdn.bcebos.com/amis/images/alice-macaw.jpg" }, "type": "page", "body": [ { "type": "avatar", "icon": "fa fa-user", "src": "$myAvatar" }, { "type": "avatar", "icon": "fa fa-user", "src": "$other" }, { "type": "avatar", "src": "$other", "icon": "fa fa-user", "text": "avatar" } ] }上面的例子演示了三种典型结果:
- 第一个头像
$myAvatar取到了图片地址,正常显示图片; - 第二个头像
$other在上下文中不存在,取值为空后src落空,于是降级渲染默认的icon; - 第三个头像同样取不到图片,但由于
text优先级高于icon,最终显示文字 "avatar"。
这一行为在 渲染器测试用例(Renderer:avatar var)中有完整覆盖,测试通过makeEnv构建页面数据域后断言快照输出。注意:此处"取不到数据导致的空 src"与下文"图片地址本身加载失败"是两种不同情况,处理路径并不相同。
形状控制:圆形、方形与圆角
通过shape可以切换头像外形,可选值为'circle'(圆形,默认)、'square'(正方形)、'rounded'(圆角):
[ { "type": "avatar", "shape": "square", "text": "AM" }, { "type": "avatar", "shape": "rounded", "text": "AM", "style": { "marginLeft": "10px" } } ]从样式源码看,_avatar.scss 中Avatar--square将border-radius设为0%,Avatar--rounded设为10%,而基础样式默认border-radius: 50%构成圆形。也就是说形状本质上就是三个圆角类名(Avatar--circle/Avatar--square/Avatar--rounded)的切换,shape的默认值'circle'在 amis-ui Avatar 组件的 defaultProps 中定义。
尺寸控制:预设大小与自定义像素
size支持字符串预设和数字像素两种写法,默认'default':
[ { "type": "avatar", "size": "large", "icon": "fa fa-user" }, { "type": "avatar", "size": "default", "icon": "fa fa-user" }, { "type": "avatar", "size": "small", "icon": "fa fa-user" }, { "type": "avatar", "size": 60, "src": "https://suda.cdn.bcebos.com/amis/images/alice-macaw.jpg" }, { "type": "avatar", "src": "https://suda.cdn.bcebos.com/amis/images/alice-macaw.jpg" }, { "type": "avatar", "size": 20, "src": "https://suda.cdn.bcebos.com/amis/images/alice-macaw.jpg" } ]三种预设字符串对应的实际尺寸(来自 _properties.scss 的 CSS 变量定义):
| size 值 | 头像尺寸 | 图标尺寸 |
|---|---|---|
large | 48px(--Avatar-size-large) | 20px |
default | 40px(--Avatar-width,同时是--Avatar-size-default) | 继承--fontSizeLg |
small | 32px(--Avatar-size-small) | 12px |
当size是数字时,amis-ui 渲染逻辑 会生成内联样式{height: size, width: size, lineHeight: size + 'px'},直接以像素控制宽高。注意文档属性表中把字符串类型写成'default' | 'normal' | 'small',但实际源码(渲染器与基础组件两处)的联合类型均为'small' | 'default' | 'large',其中'normal'是历史兼容写法,效果等同默认 40px。
这些预设值都通过px2rem()转换,会随根字号缩放,适合需要响应式适配的主题体系。编辑器插件的默认 scaffold 则以 40px 为默认尺寸(DefaultSize = 40,见 Avatar.tsx)。
gap:文字与边界的距离控制
gap控制文字(字符类型内容)距离左右两侧边界的像素,默认值 4:
[ { "type": "avatar", "text": "ejson", "gap": 2 }, { "type": "avatar", "text": "ejson", "gap": 7 } ]它的底层实现并不只是简单加内边距:amis-ui 在挂载和更新时调用setScaleByGap()(见 amis-ui/src/components/Avatar.tsx),先测量文字节点宽度(avatarChildrenRef.offsetWidth)与头像容器宽度(avatarRef.offsetWidth),当gap * 2 < 容器宽度时计算diff = 容器宽度 - gap * 2,若文字宽度超过可用宽度则按比例diff / childrenWidth缩放文字,并通过transform: scale(...) translateX(-50%)保持水平居中。因此gap实际上是"文字过多时与边框保持的最小距离",文字超出时会自动等比缩小而非溢出。这一逻辑在componentDidUpdate中会在src变化导致hasImg切换、text、children或gap改变时重新计算。
fit:图片拉伸方式
fit控制图片在头像容器内的缩放方式,默认'cover',取值与 CSSobject-fit完全对应:
[ { "type": "avatar", "fit": "cover", "src": "https://suda.cdn.bcebos.com/images/amis/plumeria.jpeg" }, { "type": "avatar", "fit": "fill", "src": "https://suda.cdn.bcebos.com/images/amis/plumeria.jpeg" }, { "type": "avatar", "fit": "contain", "src": "https://suda.cdn.bcebos.com/images/amis/plumeria.jpeg" }, { "type": "avatar", "fit": "none", "src": "https://suda.cdn.bcebos.com/images/amis/plumeria.jpeg" }, { "type": "avatar", "fit": "scale-down", "src": "https://suda.cdn.bcebos.com/images/amis/plumeria.jpeg" } ]各取值含义:
cover:等比例缩放并裁剪,铺满容器(默认值,适合正方形头像);fill:拉伸填满,不保持比例;contain:完整容纳在容器内,留白短边;none:按原尺寸展示,超出部分裁剪;scale-down:取none与contain中较小的结果。
实现上,amis-ui 渲染 会将该值直接注入<img>的style.objectFit,因此在 _avatar.scss 中img本身是width/height: 100%,具体裁切行为完全交由浏览器 object-fit 完成。编辑器插件还为其提供了中文说明:等比例裁剪长边、等比例留空短边、拉伸图片填满、按原尺寸裁剪。
draggable:是否允许拖动图片
draggable控制图片是否可被鼠标拖拽(例如拖到其他窗口):
[ { "type": "avatar", "fit": "cover", "src": "https://suda.cdn.bcebos.com/images/amis/plumeria.jpeg", "draggable": false }, { "type": "avatar", "fit": "cover", "src": "https://suda.cdn.bcebos.com/images/amis/plumeria.jpeg", "draggable": true } ]它直接透传给<img draggable={draggable}>(见 amis-ui/src/components/Avatar.tsx),等同于原生 img 的draggable属性。默认不设置该值时,浏览器行为由全局默认决定;需要阻止用户拖走头像图片时显式设置为false即可。
onError:图片加载失败后的置换逻辑
当图片地址本身加载失败时(注意:不包括变量取值为空的情况),默认行为是不做任何置换、只保留原src。通过onError可以开启"失败后降级为 text 或 icon"的能力:
{ "type": "avatar", "src": "empty", "text": "avatar", "onError": "return true;" }onError是一个字符串,它会被渲染器通过new Function('event', onError)动态构造为函数执行(见 amis/src/renderers/Avatar.tsx),参数是 React 合成事件,可通过event.nativeEvent获取原生 DOM 事件。该函数需要返回 boolean 值:
- 返回
true:图片加载失败后,用text(优先)或icon(其次)进行替换显示; - 返回
false:维持默认行为,不进行置换。
底层判定发生在 amis-ui 的 handleImageLoadError:hasImg = onError ? !onError(event) : false,随后render中hasImg === false时不再走img分支,而是顺延到文字/图标分支。之所以不包含"变量取空"的情况,是因为渲染器层已经用src || defaultAvatar做了兜底,空值根本不会进入<img>的onError路径。如果构造onError字符串时语法错误,渲染器会console.warn并回退为默认处理器(始终返回false)。
样式定制与 className
可以通过style直接控制外层 DOM 的背景与文字颜色:
{ "type": "avatar", "text": "AM", "style": { "background": "#DB3E35", "color": "#FFFFFF" } }style:透传到外层span的style,与数字size生成的宽高样式合并(见 amis-ui/src/components/Avatar.tsx),所以也可以用它覆盖背景色、透明度等任意 CSS 属性;className:追加到外层span的 class,用于配合项目自定义样式;- 默认背景色来自主题变量
--Avatar-bg: #d1d5db(灰底,见 _properties.scss),可通过覆盖该 CSS 变量统一调整头像底色。
此外,_avatar.scss 定义了 hover 效果:鼠标悬停时图片和图标transform: scale(1.1)轻微放大,属于组件内置交互,无需额外配置。
编辑器插件在「外观」面板还提供了长度、高度、圆角、文字样式、内外边距、边框、背景、阴影、透明度等可视化配置项,底层统一映射到style对象(见 amis-editor/src/plugin/Avatar.tsx)。
属性表总览
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| className | string | 外层 dom 的类名 | |
| style | object | 外层 dom 的样式 | |
| fit | 'contain'|'cover'|'fill'|'none'|'scale-down' | 'cover' | 图片相对容器的缩放方式,对应 CSSobject-fit |
| src | string | 图片地址,支持变量 | |
| defaultAvatar | string | 占位图,src为空时使用 | |
| text | string | 文字,支持变量,优先级高于 icon | |
| icon | string | 'fa fa-user' | 图标,支持变量 |
| shape | 'circle'|'square'|'rounded' | 'circle' | 形状:圆形、正方形、圆角(10% 圆角) |
| size | number|'small'|'default'|'large' | 'default' | 预设大小分别为 32 / 40 / 48px,数字则按像素设置宽高 |
| gap | number | 4 | 文字距离左右边界的最小像素,文字过宽时自动缩放 |
| alt | string | 图片无法显示时的替代文本(对应原生alt) | |
| draggable | boolean | 图片是否允许拖动 | |
| crossOrigin | 'anonymous'|'use-credentials'|'' | 图片的 CORS 属性设置,透传至<img crossOrigin> | |
| onError | string | 图片加载失败处理函数体字符串,返回true时降级为 text/icon 置换 |
补充说明:
badge(角标)属性在渲染器 Schema 中同样存在(见 packages/amis/src/renderers/Avatar.tsx),渲染器外层包裹了withBadge装饰器,因此 Avatar 也支持在头像右上角叠加 amis 角标。
事件交互:click / mouseenter / mouseleave
事件派发能力需要 amis 6.1.0 及以上版本。
Avatar 会对外派发click、mouseenter、mouseleave三个事件,可通过onEvent监听并配合actions执行动作,在 actions 中通过${事件参数名}或${event.data.[事件参数名]}获取事件数据,事件机制的详细说明见 事件动作文档。
click
鼠标点击时触发,可通过${event.context.nativeEvent}获取原生鼠标事件对象:
{ "type": "avatar", "onEvent": { "click": { "actions": [ { "actionType": "toast", "args": { "msgType": "info", "msg": "${event.context.nativeEvent.type}" } } ] } } }mouseenter
鼠标移入时触发:
{ "type": "avatar", "onEvent": { "mouseenter": { "actions": [ { "actionType": "toast", "args": { "msgType": "info", "msg": "${event.context.nativeEvent.type}" } } ] } } }mouseleave
鼠标移出时触发:
{ "type": "avatar", "onEvent": { "mouseleave": { "actions": [ { "actionType": "toast", "args": { "msgType": "info", "msg": "${event.context.nativeEvent.type}" } } ] } } }三个事件均不携带额外业务数据参数,可用的数据就是event.context.nativeEvent原生事件对象。实现层面,渲染器的三个@autobind处理器(handleClick/handleMouseEnter/handleMouseLeave)统一调用dispatchEvent(e, data)派发事件(见 packages/amis/src/renderers/Avatar.tsx),测试用例 avatar.test.tsx 通过fireEvent.click/mouseEnter/mouseLeave验证了三个事件均能正确触发toast动作并携带配置的msg。
实战组合示例:用户列表头像
结合本文所有能力,一个典型的用户列表头像配置如下:
{ "type": "page", "data": { "users": [ { "name": "Alice", "avatar": "https://suda.cdn.bcebos.com/amis/images/alice-macaw.jpg" }, { "name": "Bob" } ] }, "body": [ { "type": "each", "name": "users", "items": { "type": "avatar", "size": "large", "shape": "rounded", "src": "${avatar}", "defaultAvatar": "https://suda.cdn.bcebos.com/amis/images/ai-fake-face.jpg", "text": "${name|truncate:1}", "onError": "return true;", "style": { "background": "#1890ff", "color": "#fff" }, "onEvent": { "click": { "actions": [ { "actionType": "toast", "args": { "msg": "点击了 ${name}" } } ] } } } } ] }该示例展示了变量绑定、占位图回退、失败置换、形状尺寸、样式与事件动作的完整组合:有头像地址的用户显示图片,无头像地址的用户先尝试defaultAvatar,图片加载失败时再置换为姓名首字母文字,点击后弹出提示。
总结
Avatar 头像组件以最小配置成本覆盖了头像展示的全部常见诉求:图片 / 文字 / 图标三种内容形态、src→text→icon的严格优先级、变量动态取值、shape与size的形态控制、gap的自适应文字缩放、fit的图片裁切、onError的失败置换,以及 click / mouseenter / mouseleave 三个事件动作。如果需要在可视化编辑器中使用,可直接拖入「头像」组件,在属性面板中切换图片 / 图标 / 文字类型并调整外观,生成的 JSON 与手写配置完全一致(对应插件源码 packages/amis-editor/src/plugin/Avatar.tsx)。
【免费下载链接】amis前端低代码框架,通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考