refactor(Image-Preview): Refactor placeholder from vNode type to () => vNode

pull/8322/head
shuoxian 2025-09-01 20:11:35 +08:00
parent ea5e27224f
commit 0845fad612
5 changed files with 29 additions and 23 deletions

View File

@ -18,18 +18,18 @@ You can set different preview image. You can also customize the loading placehol
<template> <template>
<a-image <a-image
:width="200"
src="https://aliyuncdn.antdv.com/logo.png" src="https://aliyuncdn.antdv.com/logo.png"
:width="200"
:preview="{ :preview="{
src: 'http://47.100.102.7:11501/admin-api/infra/file/24/get//algorithm/execute/2025/08/20/20210628_iPhoneSE_YL_42_1755674307938_1755674703040.jpg', src: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
placeholder: h(CustomLoadingComp), placeholder: () => CustomLoadingComp,
}" }"
/> />
<a-image <a-image
:width="200" :width="200"
src="https://aliyuncdn.antdv.com/logo.png" src="https://aliyuncdn.antdv.com/logo.png"
:preview="{ :preview="{
src: 'http://47.100.102.7:11501/admin-api/infra/file/24/get//algorithm/execute/2025/08/20/20210628_iPhoneSE_YL_42_1755674307938_1755674703040.jpg', src: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
placeholder: true, placeholder: true,
}" }"
/> />

View File

@ -19,12 +19,12 @@ Previewable image.
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| alt | Image description | string | - | 2.0.0 | | alt | Image description | string | - | 2.0.0 |
| fallback | Load failure fault-tolerant src | string | - | 2.0.0 | | fallback | Load failure fault-tolerant src | string | - | 2.0.0 |
| height | Image height | string \| number | - | 2.0.0 | | height | Image height | string\| number | - | 2.0.0 |
| placeholder | Load placeholder, use default placeholder when set `true` | boolean \| slot | - | 2.0.0 | | placeholder | Load placeholder, use default placeholder when set `true` | boolean\| slot | - | 2.0.0 |
| preview | preview config, disabled when `false` | boolean \| [previewType](#previewtype) | true | 2.0.0 | | preview | preview config, disabled when `false` | boolean\| [previewType](#previewtype) | true | 2.0.0 |
| src | Image path | string | - | 2.0.0 | | src | Image path | string | - | 2.0.0 |
| previewMask | custom mask | false \| function \| slot | - | 3.2.0 | | previewMask | custom mask | false\| function \| slot | - | 3.2.0 |
| width | Image width | string \| number | - | 2.0.0 | | width | Image width | string\| number | - | 2.0.0 |
### events ### events
@ -38,11 +38,12 @@ Previewable image.
{ {
visible?: boolean; visible?: boolean;
onVisibleChange?: (visible, prevVisible) => void; onVisibleChange?: (visible, prevVisible) => void;
getContainer?: string | HTMLElement | (() => HTMLElement); getContainer: string | HTMLElement | (() => HTMLElement);
src?: string; src?: string;
maskClassName?: string; maskClassName?: string;
current?: number; current?: number;
placeholder?: (() => vNode) | boolean;
} }
``` ```
Other attributes [&lt;img>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#Attributes) Other attributes [&lt;img&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#Attributes)

View File

@ -20,12 +20,12 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*LVQ3R5JjjJEAAA
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| alt | 图像描述 | string | - | 2.0.0 | | alt | 图像描述 | string | - | 2.0.0 |
| fallback | 加载失败容错地址 | string | - | 2.0.0 | | fallback | 加载失败容错地址 | string | - | 2.0.0 |
| height | 图像高度 | string \| number | - | 2.0.0 | | height | 图像高度 | string\| number | - | 2.0.0 |
| placeholder | 加载占位, 为 `true` 时使用默认占位 | boolean \| slot | - | 2.0.0 | | placeholder | 加载占位, 为 `true` 时使用默认占位 | boolean\| slot | - | 2.0.0 |
| preview | 预览参数,为 `false` 时禁用 | boolean \| [previewType](#previewtype) | true | 2.0.0 | | preview | 预览参数,为 `false` 时禁用 | boolean\| [previewType](#previewtype) | true | 2.0.0 |
| src | 图片地址 | string | - | 2.0.0 | | src | 图片地址 | string | - | 2.0.0 |
| previewMask | 自定义 mask | false \| function \| slot | - | 3.2.0 | | previewMask | 自定义 mask | false\| function \| slot | - | 3.2.0 |
| width | 图像宽度 | string \| number | - | 2.0.0 | | width | 图像宽度 | string\| number | - | 2.0.0 |
### 事件 ### 事件
@ -43,8 +43,8 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*LVQ3R5JjjJEAAA
src?: string; src?: string;
maskClassName?: string; maskClassName?: string;
current?: number; current?: number;
placeholder?: VNode | boolean; placeholder?: (() => vNode) | boolean;
} }
``` ```
其他属性见 [&lt;img>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#Attributes) 其他属性见 [&lt;img&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#Attributes)

View File

@ -20,7 +20,7 @@ export type ImagePreviewType = Omit<
src?: string; src?: string;
visible?: boolean; visible?: boolean;
fallback?: string; fallback?: string;
placeholder?: VNode | boolean; placeholder?: boolean | (() => VNode);
onVisibleChange?: (value: boolean, prevValue: boolean) => void; onVisibleChange?: (value: boolean, prevValue: boolean) => void;
getContainer?: GetContainer | false; getContainer?: GetContainer | false;
maskClassName?: string; maskClassName?: string;

View File

@ -8,7 +8,6 @@ import {
watch, watch,
cloneVNode, cloneVNode,
ref, ref,
isVNode,
nextTick, nextTick,
} from 'vue'; } from 'vue';
import type { VNode, Ref, PropType } from 'vue'; import type { VNode, Ref, PropType } from 'vue';
@ -32,6 +31,7 @@ export interface PreviewProps extends Omit<IDialogChildProps, 'onClose' | 'mask'
src?: string; src?: string;
alt?: string; alt?: string;
rootClassName?: string; rootClassName?: string;
placeholder?: boolean | (() => VNode);
icons?: { icons?: {
rotateLeft?: VNode; rotateLeft?: VNode;
rotateRight?: VNode; rotateRight?: VNode;
@ -55,7 +55,7 @@ export const previewProps = {
alt: String, alt: String,
fallback: String, fallback: String,
placeholder: { placeholder: {
type: Object as PropType<VNode | boolean>, type: [Boolean, Function] as PropType<boolean | (() => VNode)>,
default: () => true, default: () => true,
}, },
rootClassName: String, rootClassName: String,
@ -75,7 +75,8 @@ const Preview = defineComponent({
props.icons, props.icons,
); );
// placeholder // placeholder
const isCustomPlaceholder = computed(() => isVNode(props.placeholder)); const isCustomPlaceholder = computed(() => typeof props.placeholder === 'function');
const isDefaultPlaceholder = computed(() => { const isDefaultPlaceholder = computed(() => {
return props.placeholder === true; return props.placeholder === true;
}); });
@ -88,6 +89,10 @@ const Preview = defineComponent({
status.value = 'loading'; status.value = 'loading';
}, },
); );
const renderPlaceholder = () => {
const { placeholder } = props;
return typeof placeholder === 'function' ? placeholder() : placeholder;
};
const scale = shallowRef(1); const scale = shallowRef(1);
const rotate = shallowRef(0); const rotate = shallowRef(0);
const flip = reactive({ x: 1, y: 1 }); const flip = reactive({ x: 1, y: 1 });
@ -427,7 +432,7 @@ const Preview = defineComponent({
<Spin size="large" class={`${props.prefixCls}-img-placeholder`}></Spin> <Spin size="large" class={`${props.prefixCls}-img-placeholder`}></Spin>
)} )}
{isCustomPlaceholder.value && status.value === 'loading' && ( {isCustomPlaceholder.value && status.value === 'loading' && (
<div class={`${props.prefixCls}-img-placeholder`}>{props.placeholder}</div> <div class={`${props.prefixCls}-img-placeholder`}>{renderPlaceholder()}</div>
)} )}
</div> </div>
{showLeftOrRightSwitches.value && ( {showLeftOrRightSwitches.value && (