fix(components): [image] cannot trigger event when image is loaded error (#17692)

* fix(components): [image] cannot trigger event when image is loaded error

closed #17540

* fix: use `excludeListeners` to exclude event listeners

* refactor: optimize code

* fix: replace exclude with pick

* refactor: pick container attrs

---------

Co-authored-by: zhixiaotong <947803089@qq.com>
This commit is contained in:
知晓同丶 2024-08-02 17:59:59 +08:00 committed by GitHub
parent 0f8282520f
commit aceefd7a24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,12 +1,12 @@
<template> <template>
<div ref="container" :class="[ns.b(), $attrs.class]" :style="containerStyle"> <div ref="container" v-bind="containerAttrs" :class="[ns.b(), $attrs.class]">
<slot v-if="hasLoadError" name="error"> <slot v-if="hasLoadError" name="error">
<div :class="ns.e('error')">{{ t('el.image.error') }}</div> <div :class="ns.e('error')">{{ t('el.image.error') }}</div>
</slot> </slot>
<template v-else> <template v-else>
<img <img
v-if="imageSrc !== undefined" v-if="imageSrc !== undefined"
v-bind="attrs" v-bind="imgAttrs"
:src="imageSrc" :src="imageSrc"
:loading="loading" :loading="loading"
:style="imageStyle" :style="imageStyle"
@ -57,6 +57,7 @@ import {
watch, watch,
} from 'vue' } from 'vue'
import { useEventListener, useThrottleFn } from '@vueuse/core' import { useEventListener, useThrottleFn } from '@vueuse/core'
import { fromPairs } from 'lodash-unified'
import { useAttrs, useLocale, useNamespace } from '@element-plus/hooks' import { useAttrs, useLocale, useNamespace } from '@element-plus/hooks'
import ImageViewer from '@element-plus/components/image-viewer' import ImageViewer from '@element-plus/components/image-viewer'
import { import {
@ -68,7 +69,7 @@ import {
} from '@element-plus/utils' } from '@element-plus/utils'
import { imageEmits, imageProps } from './image' import { imageEmits, imageProps } from './image'
import type { CSSProperties, StyleValue } from 'vue' import type { CSSProperties } from 'vue'
defineOptions({ defineOptions({
name: 'ElImage', name: 'ElImage',
@ -83,7 +84,21 @@ let prevOverflow = ''
const { t } = useLocale() const { t } = useLocale()
const ns = useNamespace('image') const ns = useNamespace('image')
const rawAttrs = useRawAttrs() const rawAttrs = useRawAttrs()
const attrs = useAttrs()
const containerAttrs = computed(() => {
return fromPairs(
Object.entries(rawAttrs).filter(
([key]) => /^(data-|on[A-Z])/i.test(key) || ['id', 'style'].includes(key)
)
)
})
const imgAttrs = useAttrs({
excludeListeners: true,
excludeKeys: computed<string[]>(() => {
return Object.keys(containerAttrs.value)
}),
})
const imageSrc = ref<string | undefined>() const imageSrc = ref<string | undefined>()
const hasLoadError = ref(false) const hasLoadError = ref(false)
@ -102,8 +117,6 @@ const imageKls = computed(() => [
isLoading.value && ns.is('loading'), isLoading.value && ns.is('loading'),
]) ])
const containerStyle = computed(() => rawAttrs.style as StyleValue)
const imageStyle = computed<CSSProperties>(() => { const imageStyle = computed<CSSProperties>(() => {
const { fit } = props const { fit } = props
if (isClient && fit) { if (isClient && fit) {