Appearance
Image 图片
用于展示图片,并支持加载态、错误态、底部信息和预览。
何时使用
- 展示图片缩略图、封面、附件预览或带标题说明的图片内容。
- 需要提供单图预览、预览组切换、缩放、旋转或自定义预览操作时。
- 需要在图片加载中、加载失败时提供明确反馈时。
基础用法
vue
<template>
<x-image :src="imageSrc" width="160" height="120" fit="cover" alt="示例图片" />
</template>
<script setup lang="ts">
const imageSrc =
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23e8efec%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23faf6e9%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23c8d6cd%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23a6bdb1%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%237f9e90%22%2F%3E%3C%2Fsvg%3E';
</script>适应方式
vue
<template>
<x-image
:src="imageSrc"
width="120"
height="90"
fit="cover"
title="cover"
footer-position="outer"
/>
<x-image
:src="imageSrc"
width="120"
height="90"
fit="contain"
title="contain"
footer-position="outer"
/>
<x-image
:src="imageSrc"
width="120"
height="90"
fit="fill"
title="fill"
footer-position="outer"
/>
</template>
<script setup lang="ts">
const imageSrc =
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23e8efec%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23faf6e9%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23c8d6cd%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23a6bdb1%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%237f9e90%22%2F%3E%3C%2Fsvg%3E';
</script>底部信息
vue
<template>
<x-image
:src="imageSrc"
width="180"
height="120"
title="组件封面"
description="底部信息覆盖在图片内部"
fit="cover"
/>
<x-image
:src="imageSrc"
width="180"
height="120"
title="外置说明"
description="footerPosition 设置为 outer"
footer-position="outer"
fit="cover"
/>
<x-image :src="imageSrc" width="240" height="140" title="底部操作" fit="cover">
<template #extra>
<x-button size="mini" @click="footerActionCount++">收藏 {{ footerActionCount }}</x-button>
</template>
</x-image>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const footerActionCount = ref(0);
const imageSrc =
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23e8efec%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23faf6e9%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23c8d6cd%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23a6bdb1%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%237f9e90%22%2F%3E%3C%2Fsvg%3E';
</script>加载和错误
失败占位使用中性色背景,并保留图片圆角。可通过 error / error-icon 自定义内容;修改 src 后会重新进入加载流程,支持从失败地址恢复。
vue
<template>
<x-image :src="imageSrc" width="160" height="110" show-loader fit="cover" />
<x-image src="data:image/png;base64,broken-image" width="160" height="110" alt="图片加载失败" />
<x-image src="data:image/png;base64,broken-image" width="160" height="110">
<template #error-icon><span aria-hidden="true">◇</span></template>
</x-image>
<x-image src="data:image/png;base64,broken-image" width="160" height="110">
<template #error>
<div class="image-error">无法加载图片</div>
</template>
</x-image>
</template>
<script setup lang="ts">
const imageSrc =
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23e8efec%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23faf6e9%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23c8d6cd%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23a6bdb1%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%237f9e90%22%2F%3E%3C%2Fsvg%3E';
</script>
<style scoped>
.image-error {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
color: var(--x-color-text-secondary);
background: var(--x-color-fill-2);
}
</style>更换图片与错误恢复
直接更新 src。组件会重置加载状态和旧图片节点;加载失败后可通过插槽中的按钮改回有效地址。下面的图片均是离线可用的低饱和风景插画,加载通常很快。
vue
<template>
<x-button @click="src = landscapes[0]">湖畔</x-button>
<x-button @click="src = landscapes[1]">山丘</x-button>
<x-button @click="src = 'data:image/png;base64,broken-image'">模拟失败</x-button>
<x-image
:src="src"
width="240"
height="150"
fit="cover"
show-loader
alt="可替换风景"
@load="state = '图片已加载'"
@error="state = '加载失败'"
>
<template #loader><div class="placeholder">正在准备图片…</div></template>
<template #error>
<div class="placeholder">
<span>图片暂时无法加载</span>
<x-button size="mini" @click="src = landscapes[0]">恢复图片</x-button>
</div>
</template>
</x-image>
<span aria-live="polite">{{ state }}</span>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const landscape = (sky: string, hills: string) =>
'data:image/svg+xml,' +
encodeURIComponent(
`<svg xmlns="http://www.w3.org/2000/svg" width="480" height="300"><rect width="480" height="300" fill="${sky}"/><path d="M0 230Q120 110 240 220T480 180V300H0Z" fill="${hills}"/></svg>`,
);
const landscapes = [landscape('#e8efec', '#a6bdb1'), landscape('#f0ebe4', '#bca996')];
const src = ref(landscapes[0]);
const state = ref('图片已选择');
</script>
<style scoped>
.placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12px;
width: 100%;
height: 100%;
color: var(--x-color-text-secondary);
background: var(--x-color-fill-2);
}
</style>受控预览
当前:已关闭
vue
<template>
<x-button @click="previewVisible = true">打开预览</x-button>
<x-image
v-model:preview-visible="previewVisible"
:src="imageSrc"
width="180"
height="120"
fit="cover"
@preview-visible-change="onPreviewVisibleChange"
/>
<p>当前:{{ previewVisible ? '已打开' : '已关闭' }}</p>
<p v-for="(log, index) in logs" :key="index">{{ log }}</p>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const imageSrc =
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23e8efec%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23faf6e9%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23c8d6cd%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23a6bdb1%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%237f9e90%22%2F%3E%3C%2Fsvg%3E';
const previewVisible = ref(false);
const logs = ref<string[]>([]);
const onPreviewVisibleChange = (visible: boolean) => {
logs.value = [visible ? '已打开' : '已关闭', ...logs.value].slice(0, 4);
};
</script>预览组
设置 srcList 时,预览内容以该列表为准,子图片作为打开对应下标的缩略图;缩略图与列表应保持相同顺序,也可以使用不同的缩略图与高清图片地址。不传 srcList 时,预览组自动收集子图片。
当前图片:1 / 3
vue
<template>
<x-image-preview-group
v-model:visible="visible"
v-model:current="current"
:src-list="images"
infinite
@change="onChange"
>
<x-image
v-for="(item, index) in images"
:key="item"
:src="item"
width="120"
height="84"
fit="cover"
:title="`风景 ${index + 1}`"
footer-position="outer"
/>
</x-image-preview-group>
<p>当前图片:{{ current + 1 }} / {{ images.length }}</p>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const visible = ref(false);
const current = ref(0);
const images = [
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23e8efec%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23faf6e9%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23c8d6cd%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23a6bdb1%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%237f9e90%22%2F%3E%3C%2Fsvg%3E',
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23f0ebe4%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23fcf5e6%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23d7cbbd%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23bca996%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%23998571%22%2F%3E%3C%2Fsvg%3E',
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23e9edf2%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23f7f5ef%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23c7d1df%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23a7b7ca%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%238098b2%22%2F%3E%3C%2Fsvg%3E',
];
const onChange = (index: number) => {
console.log('current image:', index);
};
</script>自定义预览操作
vue
<template>
<x-image :src="imageSrc" width="180" height="120" fit="cover">
<template #preview-actions>
<x-image-preview-action name="记录" @click="record">
<span>记</span>
</x-image-preview-action>
</template>
</x-image>
<p v-for="(log, index) in logs" :key="index">{{ log }}</p>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const imageSrc =
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23e8efec%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23faf6e9%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23c8d6cd%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23a6bdb1%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%237f9e90%22%2F%3E%3C%2Fsvg%3E';
const logs = ref<string[]>([]);
const record = () => {
logs.value = ['点击了自定义预览操作', ...logs.value].slice(0, 4);
};
</script>关闭缩略图预览
preview=false 时点击缩略图不会打开预览;在自动收集的预览组中,方向键和箭头切换会跳过该图片。
vue
<template>
<x-image
:src="imageSrc"
width="180"
height="120"
fit="cover"
:preview="false"
title="仅展示图片"
/>
</template>
<script setup lang="ts">
const imageSrc =
'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22480%22%20height%3D%22300%22%20viewBox%3D%220%200%20480%20300%22%3E%3Crect%20width%3D%22480%22%20height%3D%22300%22%20fill%3D%22%23e8efec%22%2F%3E%3Ccircle%20cx%3D%22356%22%20cy%3D%2276%22%20r%3D%2230%22%20fill%3D%22%23faf6e9%22%2F%3E%3Cpath%20d%3D%22M0%20186Q94%2098%20196%20174T480%20150V300H0Z%22%20fill%3D%22%23c8d6cd%22%2F%3E%3Cpath%20d%3D%22M0%20216Q120%20160%20230%20202T480%20190V300H0Z%22%20fill%3D%22%23a6bdb1%22%2F%3E%3Cpath%20d%3D%22M0%20264Q124%20210%20260%20250T480%20242V300H0Z%22%20fill%3D%22%237f9e90%22%2F%3E%3C%2Fsvg%3E';
</script>动态图片列表
不传 srcList 时,修改子图片地址会更新当前预览,并保留注册顺序;移除图片后下标会调整,清空列表会关闭预览。使用稳定的 key 标识每张图片。
当前图片:1 / 3
vue
<template>
<x-button :disabled="!images.length" @click="replaceFirst">替换第一张</x-button>
<x-button :disabled="!images.length" @click="images.shift()">移除第一张</x-button>
<x-button @click="images = []">清空图片</x-button>
<x-button @click="restore">恢复图片</x-button>
<x-image-preview-group v-model:visible="visible" v-model:current="current">
<x-image
v-for="item in images"
:key="item.id"
:src="item.src"
width="120"
height="84"
fit="cover"
:title="`风景 ${item.id}`"
footer-position="outer"
/>
</x-image-preview-group>
<p>{{ images.length ? `当前图片:${current + 1} / ${images.length}` : '图片列表为空' }}</p>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const makeImage = (color: string) =>
'data:image/svg+xml,' +
encodeURIComponent(
`<svg xmlns="http://www.w3.org/2000/svg" width="320" height="200"><rect width="320" height="200" fill="${color}"/></svg>`,
);
const createImages = () =>
['#a6bdb1', '#bca996', '#a7b7ca'].map((color, index) => ({
id: index + 1,
src: makeImage(color),
}));
const images = ref(createImages());
const visible = ref(false);
const current = ref(0);
const replaceFirst = () => {
if (images.value[0]) images.value[0].src = makeImage('#b8c9ba');
};
const restore = () => {
visible.value = false;
current.value = 0;
images.value = createImages();
};
</script>独立预览与自定义工具条
预览工具条使用深色半透明背景,亮暗主题保持一致。将 actionsLayout 设为空数组可仅保留自定义操作;关闭后焦点返回打开预览的按钮。
已记录 0 次
vue
<template>
<x-button @click="visible = true">打开独立预览</x-button>
<span>已记录 {{ count }} 次</span>
<x-image-preview v-model:visible="visible" :src="src" :actions-layout="[]">
<template #actions>
<x-image-preview-action name="记录" @click="count++"><span>记</span></x-image-preview-action>
</template>
</x-image-preview>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const visible = ref(false);
const count = ref(0);
const src =
'data:image/svg+xml,' +
encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" width="480" height="300"><rect width="480" height="300" fill="#c8d6cd"/></svg>',
);
</script>容器内预览
通过 popupContainer 指定宿主,可将预览限制在局部容器内;设置宽高并保留定位上下文。defaultScale 会限制在 0.25~5 倍,滚轮速率需大于 1,非法值会使用默认值。
预览仅覆盖此区域
vue
<template>
<x-button @click="visible = true">在容器内预览</x-button>
<div ref="host" class="preview-host">
<x-image-preview
v-model:visible="visible"
:src="src"
:popup-container="host"
:default-scale="0.75"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const host = ref<HTMLElement>();
const visible = ref(false);
const src =
'data:image/svg+xml,' +
encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" width="480" height="300"><rect width="480" height="300" fill="#a7b7ca"/></svg>',
);
</script>
<style scoped>
.preview-host {
position: relative;
width: 100%;
height: 300px;
overflow: hidden;
}
</style>按需导入
ts
import { Image, ImagePreview, ImagePreviewGroup, ImagePreviewAction } from 'x-next';样式按需引入(base.css 为共享基础层,多个组件只需引入一次):
ts
import 'x-next/style/base.css';
import 'x-next/style/image.css';Image Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
src | 图片地址 | string | - |
width | 图片宽度 | string | number | - |
height | 图片高度 | string | number | - |
title | 标题 | string | - |
description | 描述 | string | - |
fit | 图片适应方式 | 'contain' | 'cover' | 'fill' | 'none' | 'scale-down' | - |
alt | 图片文字描述 | string | - |
hideFooter | 是否隐藏底部信息;传 'never' 时加载错误也显示 footer | boolean | 'never' | false |
footerPosition | 底部信息位置 | 'inner' | 'outer' | 'inner' |
showLoader | 是否显示加载中效果 | boolean | false |
preview | 是否开启预览 | boolean | true |
previewVisible | 预览是否打开 | boolean | undefined |
defaultPreviewVisible | 默认是否打开预览 | boolean | false |
previewProps | 预览配置 | ImagePreviewProps | - |
footerClass | 底部区域类名 | string | array | object | - |
renderToBody | 预览是否挂载到 body | boolean | true |
Image Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
update:previewVisible | 预览显隐变化时触发 | visible: boolean |
preview-visible-change | 预览显隐变化时触发 | visible: boolean |
load | 当前图片加载成功 | event: Event |
error | 当前图片加载失败 | event: Event |
Image Slots
| 插槽名 | 说明 |
|---|---|
error-icon | 自定义错误图标 |
error | 自定义错误内容 |
loader | 自定义加载内容 |
extra | 底部额外内容 |
preview-actions | 预览额外操作项 |
ImagePreview Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
src | 图片地址 | string | - |
visible | 是否显示预览 | boolean | undefined |
defaultVisible | 默认是否显示预览 | boolean | false |
maskClosable | 点击遮罩是否关闭 | boolean | true |
closable | 是否显示关闭按钮 | boolean | true |
actionsLayout | 操作项布局 | string[] | ['fullScreen', 'rotateRight', 'rotateLeft', 'zoomIn', 'zoomOut', 'originalSize'] |
popupContainer | 弹出层挂载容器 | string | HTMLElement | document.body |
escToClose | 是否支持 Esc 关闭 | boolean | true |
wheelZoom | 是否支持滚轮缩放 | boolean | true |
keyboard | 是否支持键盘控制 | boolean | true |
defaultScale | 默认缩放比 | number | 1 |
zoomRate | 缩放速率 | number | 1.1 |
renderToBody | 是否通过 Teleport 挂载到宿主容器 | boolean | true |
ImagePreview Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
update:visible | 预览显隐变化时触发 | visible: boolean |
close | 点击关闭按钮、遮罩或按 Esc 关闭时触发 | - |
ImagePreview Slots
| 插槽名 | 说明 |
|---|---|
actions | 自定义额外操作项 |
ImagePreviewGroup Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
srcList | 图片列表;设置后不再收集子 Image 的图片信息 | string[] | - |
current | 当前图片下标 | number | undefined |
defaultCurrent | 默认图片下标 | number | 0 |
infinite | 是否无限循环 | boolean | false |
visible | 是否显示预览 | boolean | undefined |
defaultVisible | 默认是否显示预览 | boolean | false |
maskClosable | 点击遮罩是否关闭 | boolean | true |
closable | 是否显示关闭按钮 | boolean | true |
actionsLayout | 操作项布局 | string[] | ['fullScreen', 'rotateRight', 'rotateLeft', 'zoomIn', 'zoomOut', 'originalSize'] |
popupContainer | 弹出层挂载容器 | string | HTMLElement | - |
renderToBody | 是否挂载到 body | boolean | true |
ImagePreviewGroup Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
change | 切换图片时触发 | index: number |
update:current | 当前图片下标变化时触发 | index: number |
visible-change | 预览显隐变化时触发 | visible: boolean |
update:visible | 预览显隐变化时触发 | visible: boolean |
ImagePreviewGroup Slots
| 插槽名 | 说明 |
|---|---|
default | 图片列表内容 |
actions | 自定义额外操作项,插槽参数为 { url } |
ImagePreviewAction Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
name | 操作项名称,会用于 tooltip 和可访问标签 | string | - |
disabled | 是否禁用 | boolean | false |
交互说明
- 预览打开后支持鼠标拖拽图片、滚轮缩放图片。
- 图片加载成功后可聚焦缩略图,通过 Enter / Space 打开预览;加载中、错误或
preview=false时不会打开。 - Tab 在预览内循环,关闭或卸载时恢复打开前的焦点;快捷键仅作用于最上层弹层。
- 工具条默认深色半透明,悬浮和焦点使用浅色透明高亮。可覆盖
--x-image-preview-color-toolbar-bg等 token 定制。 - 满屏按容器较小轴缩放以保留完整图片,并遵守 0.25~5 倍范围。预览失败显示明确反馈,组内可继续切换下一张。
keyboard为true时,Esc 关闭预览,左右方向键切换预览组,上下方向键缩放,Space 还原到原始大小。- 使用受控的
current/visible时,请接收对应更新事件或使用v-model;列表为空时预览不会显示。 srcList初始下标超界时会发送update:current请求修正,受控模式等待父组件更新下标后显示有效图片。