feat(components): [image-viewer] add setActiveItem method (#9389)

* fix(components): [image-viewer] initialIndex lost reactivity

* feat(components): [image-viewer] add `setActiveItem` method

* feat: expose instance type

* chore: add test case

* chore: update docs
This commit is contained in:
zz 2022-08-26 18:18:08 +08:00 committed by GitHub
parent e16cb4f97e
commit e33a279556
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 10 deletions

View File

@ -111,3 +111,9 @@ image/image-preview
| ---------- | ------------------------------------------------------------------------------------------------- | ------------------------- |
| `close` | trigger when clicking on close button or when `hide-on-click-modal` enabled clicking on backdrop. | `() => void` |
| `switch` | trigger when switching images. | `(index: number) => void` |
## Image Viewer Methods
| Method | Description | Parameters |
| ------------- | --------------------- | ----------------------------------------------------- |
| setActiveItem | manually switch image | index of the image to be switched to, starting from 0 |

View File

@ -44,4 +44,26 @@ describe('<image-viewer />', () => {
expect(wrapper.emitted('close')).toBeDefined()
wrapper.unmount()
})
test('manually switch image', async () => {
const wrapper = mount({
props: {
urlList: [IMAGE_SUCCESS, IMAGE_SUCCESS],
},
})
await doubleWait()
const viewer = wrapper.find('.el-image-viewer__wrapper')
expect(viewer.exists()).toBe(true)
const imgList = wrapper.findAll('.el-image-viewer__img')
expect(imgList[0].attributes('style')).not.contains('display: none;')
expect(imgList[1].attributes('style')).contains('display: none;')
wrapper.vm.setActiveItem(1)
await doubleWait()
expect(imgList[0].attributes('style')).contains('display: none;')
expect(imgList[1].attributes('style')).not.contains('display: none;')
wrapper.unmount()
})
})

View File

@ -4,7 +4,9 @@ import {
isNumber,
mutable,
} from '@element-plus/utils'
import type { Component, ExtractPropTypes } from 'vue'
import type ImageViewer from './image-viewer.vue'
export type ImageViewerAction =
| 'zoomIn'
@ -53,3 +55,5 @@ export interface ImageViewerMode {
name: string
icon: Component
}
export type ImageViewerInstance = InstanceType<typeof ImageViewer>

View File

@ -63,7 +63,7 @@
<div :class="ns.e('canvas')">
<img
v-for="(url, i) in urlList"
v-show="i === index"
v-show="i === activeIndex"
:ref="(el) => (imgRefs[i] = el as HTMLImageElement)"
:key="url"
:src="url"
@ -142,7 +142,7 @@ const imgRefs = ref<HTMLImageElement[]>([])
const scopeEventListener = effectScope()
const loading = ref(true)
const index = ref(props.initialIndex)
const activeIndex = ref(props.initialIndex)
const mode = shallowRef<ImageViewerMode>(modes.CONTAIN)
const transform = ref({
scale: 1,
@ -158,15 +158,15 @@ const isSingle = computed(() => {
})
const isFirst = computed(() => {
return index.value === 0
return activeIndex.value === 0
})
const isLast = computed(() => {
return index.value === props.urlList.length - 1
return activeIndex.value === props.urlList.length - 1
})
const currentImg = computed(() => {
return props.urlList[index.value]
return props.urlList[activeIndex.value]
})
const imgStyle = computed(() => {
@ -318,16 +318,19 @@ function toggleMode() {
reset()
}
function setActiveItem(index: number) {
const len = props.urlList.length
activeIndex.value = (index + len) % len
}
function prev() {
if (isFirst.value && !props.infinite) return
const len = props.urlList.length
index.value = (index.value - 1 + len) % len
setActiveItem(activeIndex.value - 1)
}
function next() {
if (isLast.value && !props.infinite) return
const len = props.urlList.length
index.value = (index.value + 1) % len
setActiveItem(activeIndex.value + 1)
}
function handleActions(action: ImageViewerAction, options = {}) {
@ -372,7 +375,7 @@ watch(currentImg, () => {
})
})
watch(index, (val) => {
watch(activeIndex, (val) => {
reset()
emit('switch', val)
})
@ -383,4 +386,9 @@ onMounted(() => {
// focus wrapper so arrow key can't cause inner scroll behavior underneath
wrapper.value?.focus?.()
})
defineExpose({
/** @description manually switch image */
setActiveItem,
})
</script>