mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(ImagePreview): add preview image slot (#11133)
This commit is contained in:
parent
685351799e
commit
7d48159e65
@ -157,6 +157,9 @@ export default defineComponent({
|
||||
rootHeight={state.rootHeight}
|
||||
onScale={emitScale}
|
||||
onClose={emitClose}
|
||||
v-slots={{
|
||||
image: slots.image,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Swipe>
|
||||
|
@ -47,7 +47,7 @@ export default defineComponent({
|
||||
|
||||
emits: ['scale', 'close'],
|
||||
|
||||
setup(props, { emit }) {
|
||||
setup(props, { emit, slots }) {
|
||||
const state = reactive({
|
||||
scale: 1,
|
||||
moveX: 0,
|
||||
@ -293,14 +293,20 @@ export default defineComponent({
|
||||
onTouchend={onTouchEnd}
|
||||
onTouchcancel={onTouchEnd}
|
||||
>
|
||||
<Image
|
||||
v-slots={imageSlots}
|
||||
src={props.src}
|
||||
fit="contain"
|
||||
class={bem('image', { vertical: vertical.value })}
|
||||
style={imageStyle.value}
|
||||
onLoad={onLoad}
|
||||
/>
|
||||
{slots.image ? (
|
||||
<div class={bem('image-wrap')}>
|
||||
{slots.image({ src: props.src })}
|
||||
</div>
|
||||
) : (
|
||||
<Image
|
||||
v-slots={imageSlots}
|
||||
src={props.src}
|
||||
fit="contain"
|
||||
class={bem('image', { vertical: vertical.value })}
|
||||
style={imageStyle.value}
|
||||
onLoad={onLoad}
|
||||
/>
|
||||
)}
|
||||
</SwipeItem>
|
||||
);
|
||||
};
|
||||
|
@ -118,6 +118,42 @@ export default {
|
||||
};
|
||||
```
|
||||
|
||||
### Component Call use image slot
|
||||
|
||||
```html
|
||||
<van-image-preview v-model:show="show" :images="images" @change="onChange">
|
||||
<template #image="{src}">
|
||||
<video style="width: 100%;" controls><source :src="src" /></video>
|
||||
</template>
|
||||
</van-image-preview>
|
||||
```
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const show = ref(false);
|
||||
const index = ref(0);
|
||||
const images = [
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
];
|
||||
const onChange = (newIndex) => {
|
||||
index.value = newIndex;
|
||||
};
|
||||
|
||||
return {
|
||||
show,
|
||||
index,
|
||||
images,
|
||||
onChange,
|
||||
};
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Options
|
||||
@ -218,6 +254,7 @@ imagePreviewRef.value?.swipeTo(1);
|
||||
| --- | --- | --- |
|
||||
| index | Custom index | { index: index of current image } |
|
||||
| cover | Custom content that covers the image preview | - |
|
||||
| image | Custom image slot | { src: current image src } |
|
||||
|
||||
### onClose Parameters
|
||||
|
||||
|
@ -172,6 +172,42 @@ export default {
|
||||
};
|
||||
```
|
||||
|
||||
### 组件调用 - 使用 image 插槽
|
||||
|
||||
```html
|
||||
<van-image-preview v-model:show="show" :images="images" @change="onChange">
|
||||
<template #image="{src}">
|
||||
<video style="width: 100%;" controls><source :src="src" /></video>
|
||||
</template>
|
||||
</van-image-preview>
|
||||
```
|
||||
|
||||
```js
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const show = ref(false);
|
||||
const index = ref(0);
|
||||
const images = [
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
];
|
||||
const onChange = (newIndex) => {
|
||||
index.value = newIndex;
|
||||
};
|
||||
|
||||
return {
|
||||
show,
|
||||
index,
|
||||
images,
|
||||
onChange,
|
||||
};
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Options
|
||||
@ -279,6 +315,7 @@ imagePreviewRef.value?.swipeTo(1);
|
||||
| ----- | ------------------------------ | ------------------------- |
|
||||
| index | 自定义页码内容 | { index: 当前图片的索引 } |
|
||||
| cover | 自定义覆盖在图片预览上方的内容 | - |
|
||||
| image | 自定义图片插槽 | { src: 当前资源地址 } |
|
||||
|
||||
### onClose 回调参数
|
||||
|
||||
|
@ -17,6 +17,7 @@ const t = useTranslate({
|
||||
customConfig: '传入配置项',
|
||||
startPosition: '指定初始位置',
|
||||
componentCall: '组件调用',
|
||||
componentImage: '组件调用使用image插槽',
|
||||
index: (index: number) => `第${index + 1}页`,
|
||||
},
|
||||
'en-US': {
|
||||
@ -28,6 +29,7 @@ const t = useTranslate({
|
||||
customConfig: 'Custom Config',
|
||||
startPosition: 'Set Start Position',
|
||||
componentCall: 'Component Call',
|
||||
componentImage: 'Component Call use image slot',
|
||||
index: (index: number) => `Page: ${index}`,
|
||||
},
|
||||
});
|
||||
@ -39,9 +41,19 @@ const images = [
|
||||
cdnURL('apple-4.jpeg'),
|
||||
];
|
||||
|
||||
const imagesSlot = [
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
'https://www.w3school.com.cn/i/movie.ogg',
|
||||
];
|
||||
|
||||
const show = ref(false);
|
||||
const index = ref(0);
|
||||
|
||||
const showSlot = ref(false);
|
||||
const indexSlot = ref(0);
|
||||
|
||||
const onClose = () => Toast(t('closed'));
|
||||
|
||||
const beforeClose = () =>
|
||||
@ -59,6 +71,14 @@ const onChange = (newIndex: number) => {
|
||||
index.value = newIndex;
|
||||
};
|
||||
|
||||
const showComponentCallSlot = () => {
|
||||
showSlot.value = true;
|
||||
};
|
||||
|
||||
const onChangeSlot = (newIndex: number) => {
|
||||
indexSlot.value = newIndex;
|
||||
};
|
||||
|
||||
const showImagePreview = (options: Partial<ImagePreviewOptions> = {}) => {
|
||||
const instance = ImagePreview({
|
||||
images,
|
||||
@ -110,4 +130,21 @@ const showImagePreview = (options: Partial<ImagePreviewOptions> = {}) => {
|
||||
<template #index>{{ t('index', index) }}</template>
|
||||
</van-image-preview>
|
||||
</demo-block>
|
||||
|
||||
<demo-block card :title="t('componentImage')">
|
||||
<van-cell
|
||||
is-link
|
||||
:value="t('componentImage')"
|
||||
@click="showComponentCallSlot"
|
||||
/>
|
||||
<van-image-preview
|
||||
v-model:show="showSlot"
|
||||
:images="imagesSlot"
|
||||
@change="onChangeSlot"
|
||||
>
|
||||
<template #image="{ src }">
|
||||
<video style="width: 100%" controls><source :src="src" /></video>
|
||||
</template>
|
||||
</van-image-preview>
|
||||
</demo-block>
|
||||
</template>
|
||||
|
@ -38,7 +38,8 @@
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&__image {
|
||||
&__image,
|
||||
&__image-wrap {
|
||||
width: 100%;
|
||||
transition-property: transform;
|
||||
|
||||
@ -47,7 +48,8 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
img {
|
||||
img,
|
||||
video {
|
||||
// disable desktop browser image drag
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
@ -254,3 +254,36 @@ test('zoom out', async () => {
|
||||
|
||||
restore();
|
||||
});
|
||||
|
||||
test('should render image slot correctly', async () => {
|
||||
const wrapper = mount(ImagePreviewComponent, {
|
||||
props: {
|
||||
show: true,
|
||||
images,
|
||||
},
|
||||
slots: {
|
||||
image: ({ src }) => `<img class="test-img" src="${src}" />`,
|
||||
},
|
||||
});
|
||||
|
||||
await later();
|
||||
|
||||
expect(wrapper.html().includes('test-img')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should render image slot correctly 2', async () => {
|
||||
const wrapper = mount(ImagePreviewComponent, {
|
||||
props: {
|
||||
show: true,
|
||||
images,
|
||||
},
|
||||
slots: {
|
||||
image: ({ src }) =>
|
||||
`<video style="width: 100%;" controls><source src="${src}" /></video>`,
|
||||
},
|
||||
});
|
||||
|
||||
await later();
|
||||
|
||||
expect(wrapper.html().includes('video')).toBeTruthy();
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user