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

@ -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

@ -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 && (