fix(Image): should not render img when error
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
import { ref, watch, computed, PropType } from 'vue';
|
||||
import { createNamespace, isDef, addUnit } from '../utils';
|
||||
import Icon from '../icon';
|
||||
|
||||
const [createComponent, bem] = createNamespace('image');
|
||||
|
||||
export type ImageFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
|
||||
|
||||
export default createComponent({
|
||||
props: {
|
||||
src: String,
|
||||
alt: String,
|
||||
fit: String as PropType<ImageFit>,
|
||||
round: Boolean,
|
||||
width: [Number, String],
|
||||
height: [Number, String],
|
||||
radius: [Number, String],
|
||||
lazyLoad: Boolean,
|
||||
showError: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showLoading: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
errorIcon: {
|
||||
type: String,
|
||||
default: 'photo-fail',
|
||||
},
|
||||
loadingIcon: {
|
||||
type: String,
|
||||
default: 'photo',
|
||||
},
|
||||
},
|
||||
|
||||
emits: ['load', 'error'],
|
||||
|
||||
setup(props, { emit, slots }) {
|
||||
const error = ref(false);
|
||||
const loading = ref(true);
|
||||
const imageRef = ref();
|
||||
|
||||
const style = computed(() => {
|
||||
const style: Record<string, unknown> = {};
|
||||
|
||||
if (isDef(props.width)) {
|
||||
style.width = addUnit(props.width);
|
||||
}
|
||||
|
||||
if (isDef(props.height)) {
|
||||
style.height = addUnit(props.height);
|
||||
}
|
||||
|
||||
if (isDef(props.radius)) {
|
||||
style.overflow = 'hidden';
|
||||
style.borderRadius = addUnit(props.radius);
|
||||
}
|
||||
|
||||
return style;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.src,
|
||||
() => {
|
||||
error.value = false;
|
||||
loading.value = true;
|
||||
}
|
||||
);
|
||||
|
||||
const onLoad = (event: Event) => {
|
||||
loading.value = false;
|
||||
emit('load', event);
|
||||
};
|
||||
|
||||
const onError = (event: Event) => {
|
||||
error.value = true;
|
||||
loading.value = false;
|
||||
emit('error', event);
|
||||
};
|
||||
|
||||
const renderLoadingIcon = () => {
|
||||
if (slots.loading) {
|
||||
return slots.loading();
|
||||
}
|
||||
|
||||
return <Icon name={props.loadingIcon} class={bem('loading-icon')} />;
|
||||
};
|
||||
|
||||
const renderErrorIcon = () => {
|
||||
if (slots.error) {
|
||||
return slots.error();
|
||||
}
|
||||
|
||||
return <Icon name={props.errorIcon} class={bem('error-icon')} />;
|
||||
};
|
||||
|
||||
const renderPlaceholder = () => {
|
||||
if (loading.value && props.showLoading) {
|
||||
return <div class={bem('loading')}>{renderLoadingIcon()}</div>;
|
||||
}
|
||||
if (error.value && props.showError) {
|
||||
return <div class={bem('error')}>{renderErrorIcon()}</div>;
|
||||
}
|
||||
};
|
||||
|
||||
const renderImage = () => {
|
||||
if (error.value || !props.src) {
|
||||
return;
|
||||
}
|
||||
|
||||
const attrs = {
|
||||
alt: props.alt,
|
||||
class: bem('img'),
|
||||
style: {
|
||||
objectFit: props.fit,
|
||||
},
|
||||
};
|
||||
|
||||
if (props.lazyLoad) {
|
||||
return <img ref={imageRef} v-lazy={props.src} {...attrs} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<img src={props.src} onLoad={onLoad} onError={onError} {...attrs} />
|
||||
);
|
||||
};
|
||||
|
||||
return () => (
|
||||
<div class={bem({ round: props.round })} style={style.value}>
|
||||
{renderImage()}
|
||||
{renderPlaceholder()}
|
||||
{slots.default?.()}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
// TODO: lazyLoad
|
||||
// created() {
|
||||
// const { $Lazyload } = this;
|
||||
|
||||
// if ($Lazyload && inBrowser) {
|
||||
// $Lazyload.$on('loaded', this.onLazyLoaded);
|
||||
// $Lazyload.$on('error', this.onLazyLoadError);
|
||||
// }
|
||||
// },
|
||||
|
||||
// beforeUnmount() {
|
||||
// const { $Lazyload } = this;
|
||||
|
||||
// if ($Lazyload) {
|
||||
// $Lazyload.$off('loaded', this.onLazyLoaded);
|
||||
// $Lazyload.$off('error', this.onLazyLoadError);
|
||||
// }
|
||||
// },
|
||||
|
||||
// methods: {
|
||||
// onLazyLoaded({ el }) {
|
||||
// if (el === this.$refs.image && this.loading) {
|
||||
// this.onLoad();
|
||||
// }
|
||||
// },
|
||||
|
||||
// onLazyLoadError({ el }) {
|
||||
// if (el === this.$refs.image && !this.error) {
|
||||
// this.onError();
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
});
|
||||
Reference in New Issue
Block a user