Attachments 输入附件
用于展示一组附件信息集合。
何时使用
Attachments 组件用于需要展示一组附件信息集合的场景。
代码演示
基本
占位信息
修改占位信息。
Click or Drop files here
Support file type: image, video, audio, document, etc.Custom Placeholder Node
ts
<script setup lang="tsx">
import { CloudUploadOutlined } from '@ant-design/icons-vue';
import { Button, Flex, Result, theme } from 'ant-design-vue';
import { Attachments, type AttachmentsProps } from 'ant-design-x-vue';
import { computed, type CSSProperties, ref } from 'vue';
defineOptions({ name: 'AXAttachmentPlaceholder' });
const presetFiles: AttachmentsProps['items'] = [
{
uid: '1',
name: 'uploading file.xlsx',
status: 'uploading',
url: 'http://www.baidu.com/xxx.png',
percent: 93,
},
{
uid: '2',
name: 'uploaded file.docx',
status: 'done',
size: 123456,
description: 'Customize description',
url: 'http://www.baidu.com/yyy.png',
},
{
uid: '3',
name: 'upload error with long text file name.zip',
status: 'error',
response: 'Server Error 500', // custom error message to show
url: 'http://www.baidu.com/zzz.png',
},
{
uid: '4',
name: 'image uploading preview.png',
status: 'uploading',
percent: 33,
thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
{
uid: '5',
name: 'image done preview.png',
status: 'done',
size: 123456,
thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
{
uid: '6',
name: 'image error preview.png',
status: 'error',
response: 'Server Error 500', // custom error message to show
thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
];
type ExtractFunc<T> = T extends (...args: any) => any ? T : never;
const getPlaceholderFn = (
inlinePlaceholder: ReturnType<ExtractFunc<AttachmentsProps['placeholder']>>,
) => {
return (type: 'inline' | 'drop') =>
type === 'drop'
? {
title: 'Drop file here',
}
: inlinePlaceholder;
};
const { token } = theme.useToken();
const items = ref<AttachmentsProps['items']>([]);
const sharedBorderStyle = computed<CSSProperties>(() => ({
borderRadius: token.value.borderRadius,
overflow: 'hidden',
background: token.value.colorBgContainer,
}));
const sharedAttachmentProps = computed<AttachmentsProps>(() => ({
beforeUpload: () => false,
items: items.value,
onChange: ({ fileList }) => {
console.log('onChange:', fileList);
items.value = fileList;
},
}));
defineRender(() => {
return (
<Flex
vertical
gap="middle"
style={{
padding: token.value.padding,
background: token.value.colorBgContainerDisabled,
}}
>
<div style={sharedBorderStyle.value}>
<Attachments
{...sharedAttachmentProps.value}
placeholder={getPlaceholderFn({
icon: <CloudUploadOutlined />,
title: 'Click or Drop files here',
description: 'Support file type: image, video, audio, document, etc.',
})}
/>
</div>
<div style={sharedBorderStyle.value}>
<Attachments
{...sharedAttachmentProps.value}
placeholder={getPlaceholderFn(
<Result
title="Custom Placeholder Node"
icon={<CloudUploadOutlined />}
extra={<Button type="primary">Do Upload</Button>}
style={{ padding: 0 }}
/>,
)}
/>
</div>
<Flex gap="middle">
<Button
style={{ flex: '1 1 50%' }}
disabled={!!items.value.length}
type="primary"
onClick={() => {
items.value = presetFiles
}}
>
Fill Files
</Button>
<Button
style={{ flex: '1 1 50%' }}
disabled={!items.value.length}
onClick={() => {
items.value = []
}}
>
Reset Files
</Button>
</Flex>
</Flex>
)
});
</script>
隐藏源代码
超出样式
控制附件超出区域长度时的展示方式。

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview

Preview
Click or Drop files here
Support file type: image, video, audio, document, etc.ts
<script setup lang="tsx">
import { CloudUploadOutlined } from '@ant-design/icons-vue';
import { Flex, Segmented, Switch } from 'ant-design-vue';
import { Attachments, type AttachmentsProps } from 'ant-design-x-vue';
import { ref } from 'vue';
defineOptions({ name: 'AXAttachmentOverflow' });
const presetFiles: AttachmentsProps['items'] = Array.from({ length: 30 }).map((_, index) => ({
uid: String(index),
name: `file-${index}.jpg`,
status: 'done',
thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
}));
const overflow = ref<AttachmentsProps['overflow']>('wrap');
const items = ref<AttachmentsProps['items']>(presetFiles);
const disabled = ref(false);
defineRender(() => {
return (
<Flex vertical gap="middle">
<Flex gap="middle" align="center">
<Segmented
options={[
{ value: 'wrap', label: 'Wrap' },
{ value: 'scrollX', label: 'Scroll X' },
{ value: 'scrollY', label: 'Scroll Y' },
]}
value={overflow.value}
onChange={(v) => {
overflow.value = v as AttachmentsProps['overflow'];
}}
style={{ marginInlineEnd: 'auto' }}
/>
<Switch
checked={items.value.length !== 0}
onChange={() => {
items.value = items.value.length ? [] : presetFiles
}}
checkedChildren="Data"
unCheckedChildren="Data"
/>
<Switch
checked={disabled.value}
onChange={(v) => {
disabled.value = v as boolean;
}}
checkedChildren="Disabled"
unCheckedChildren="Disabled"
/>
</Flex>
<Attachments
overflow={overflow.value}
items={items.value}
onChange={(info) => {
items.value = info.fileList
}}
beforeUpload={() => false}
placeholder={{
icon: <CloudUploadOutlined />,
title: 'Click or Drop files here',
description: 'Support file type: image, video, audio, document, etc.',
}}
disabled={disabled.value}
/>
</Flex>
)
})
</script>
隐藏源代码
组合示例
文件卡片
自定义卡片图标
API
Attachments Props
继承 antdv Upload 属性。
| 属性 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| classNames | 自定义样式类名,见下 | Record<string, string> | - | - |
| disabled | 是否禁用 | boolean | false | - |
| getDropContainer | 设置拖拽时,可以释放文件的区域 | () => HTMLElement | - | - |
| items | 附件列表,同 Upload fileList | Attachment[] | - | - |
| overflow | 文件列表超出时样式 | 'wrap' | 'scrollX' | 'scrollY' | - | - |
| placeholder | 没有文件时的占位信息 | PlaceholderType | ((type: 'inline' | 'drop') => PlaceholderType) | - | - |
| rootClassName | 根节点的样式类名 | string | - | - |
| rootStyle | 根节点的样式对象 | CSSProperties | - | - |
| styles | 自定义样式对象,见下 | Record<string, CSSProperties> | - | - |
| imageProps | 图片属性,同 antdv Image 属性 | ImageProps | - | - |
tsx
interface PlaceholderType {
icon?: VNode;
title?: VNode | string;
description?: VNode | string;
}Attachments Slots
| 插槽名 | 说明 | 类型 |
|---|---|---|
| placeholder | 没有文件时的占位信息 | { type: "inline" | "drop" } |
Attachments Expose
| 属性 | 说明 | 类型 | 版本 |
|---|---|---|---|
| nativeElement | 获取原生节点 | HTMLElement | - |
| upload | 手工调用上传文件 | (file: File | File[] | FileList) => void | - |
Attachments.FileCard Props
| 属性 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| item | 附件,同 Upload UploadFile | Attachment | - | - |
| onRemove | 点击移除文件时的回调,返回值为 false 时不移除。支持返回一个 Promise 对象,Promise 对象 resolve(false) 或 reject 时不移除 | (item: Attachment) => boolean | Promise | - | - |
| icon | 自定义图标 | VNode | PresetIcons | - | - |
| type | 定义文件类型,当类型为image时,会展示为图片预览模式 | 'file' | 'image' | file | - |
ts
type PresetIcons = 'default' | 'excel' | 'image' | 'markdown' | 'pdf' | 'ppt' | 'word' | 'zip' | 'video' | 'audio';Semantic DOM
Upload File
Drag or click to upload file.placeholder
占位符

Preview

Preview

Preview
list
列表容器item
列表项upload
上传按钮
主题变量(Design Token)
贡献者
贡献者
正在加载贡献者信息...