mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-05-09 00:48:56 +08:00
refactor(Image): refactor with composition api
This commit is contained in:
parent
796ddca896
commit
982a9d16da
@ -1,4 +1,5 @@
|
|||||||
import { createNamespace, isDef, addUnit, inBrowser } from '../utils';
|
import { ref, watch, computed } from 'vue';
|
||||||
|
import { createNamespace, isDef, addUnit } from '../utils';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
|
|
||||||
const [createComponent, bem] = createNamespace('image');
|
const [createComponent, bem] = createNamespace('image');
|
||||||
@ -31,156 +32,138 @@ export default createComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['load', 'error', 'click'],
|
emits: ['load', 'error'],
|
||||||
|
|
||||||
data() {
|
setup(props, { emit, slots }) {
|
||||||
return {
|
const error = ref(false);
|
||||||
loading: true,
|
const loading = ref(true);
|
||||||
error: false,
|
const imageRef = ref(null);
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
const style = computed(() => {
|
||||||
src() {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
style() {
|
|
||||||
const style = {};
|
const style = {};
|
||||||
|
|
||||||
if (isDef(this.width)) {
|
if (isDef(props.width)) {
|
||||||
style.width = addUnit(this.width);
|
style.width = addUnit(props.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDef(this.height)) {
|
if (isDef(props.height)) {
|
||||||
style.height = addUnit(this.height);
|
style.height = addUnit(props.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDef(this.radius)) {
|
if (isDef(props.radius)) {
|
||||||
style.overflow = 'hidden';
|
style.overflow = 'hidden';
|
||||||
style.borderRadius = addUnit(this.radius);
|
style.borderRadius = addUnit(props.radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
},
|
});
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
watch(
|
||||||
const { $Lazyload } = this;
|
computed(() => props.src),
|
||||||
|
() => {
|
||||||
if ($Lazyload && inBrowser) {
|
error.value = false;
|
||||||
$Lazyload.$on('loaded', this.onLazyLoaded);
|
loading.value = true;
|
||||||
$Lazyload.$on('error', this.onLazyLoadError);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeUnmount() {
|
|
||||||
const { $Lazyload } = this;
|
|
||||||
|
|
||||||
if ($Lazyload) {
|
|
||||||
$Lazyload.$off('loaded', this.onLazyLoaded);
|
|
||||||
$Lazyload.$off('error', this.onLazyLoadError);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
onLoad(event) {
|
|
||||||
this.loading = false;
|
|
||||||
this.$emit('load', event);
|
|
||||||
},
|
|
||||||
|
|
||||||
onLazyLoaded({ el }) {
|
|
||||||
if (el === this.$refs.image && this.loading) {
|
|
||||||
this.onLoad();
|
|
||||||
}
|
}
|
||||||
},
|
);
|
||||||
|
|
||||||
onLazyLoadError({ el }) {
|
const onLoad = (event) => {
|
||||||
if (el === this.$refs.image && !this.error) {
|
loading.value = false;
|
||||||
this.onError();
|
emit('load', event);
|
||||||
}
|
};
|
||||||
},
|
|
||||||
|
|
||||||
onError(event) {
|
const onError = (event) => {
|
||||||
this.error = true;
|
error.value = true;
|
||||||
this.loading = false;
|
loading.value = false;
|
||||||
this.$emit('error', event);
|
emit('error', event);
|
||||||
},
|
};
|
||||||
|
|
||||||
onClick(event) {
|
const renderLoadingIcon = () => {
|
||||||
this.$emit('click', event);
|
if (slots.loading) {
|
||||||
},
|
return slots.loading();
|
||||||
|
|
||||||
genPlaceholder() {
|
|
||||||
if (this.loading && this.showLoading) {
|
|
||||||
return (
|
|
||||||
<div class={bem('loading')}>
|
|
||||||
{this.$slots.loading ? (
|
|
||||||
this.$slots.loading()
|
|
||||||
) : (
|
|
||||||
<Icon name={this.loadingIcon} class={bem('loading-icon')} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.error && this.showError) {
|
return <Icon name={props.loadingIcon} class={bem('loading-icon')} />;
|
||||||
return (
|
};
|
||||||
<div class={bem('error')}>
|
|
||||||
{this.$slots.error ? (
|
const renderErrorIcon = () => {
|
||||||
this.$slots.error()
|
if (slots.error) {
|
||||||
) : (
|
return slots.error();
|
||||||
<Icon name={this.errorIcon} class={bem('error-icon')} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
genImage() {
|
return <Icon name={props.errorIcon} class={bem('error-icon')} />;
|
||||||
const imgData = {
|
};
|
||||||
alt: this.alt,
|
|
||||||
class: bem('img'),
|
|
||||||
style: {
|
|
||||||
objectFit: this.fit,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.error) {
|
const renderPlaceholder = () => {
|
||||||
|
if (props.loading && props.showLoading) {
|
||||||
|
return <div class={bem('loading')}>{renderLoadingIcon()}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.error && props.showError) {
|
||||||
|
return <div class={bem('error')}>{renderErrorIcon()}</div>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderImage = () => {
|
||||||
|
if (props.error || !props.src) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lazyLoad) {
|
const attrs = {
|
||||||
return <img ref="image" vLazy={this.src} {...imgData} />;
|
alt: props.alt,
|
||||||
|
class: bem('img'),
|
||||||
|
style: {
|
||||||
|
objectFit: props.fit,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (props.lazyLoad) {
|
||||||
|
return <img ref={imageRef} vLazy={props.src} {...attrs} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.src) {
|
return (
|
||||||
return (
|
<img src={props.src} onLoad={onLoad} onError={onError} {...attrs} />
|
||||||
<img
|
);
|
||||||
src={this.src}
|
};
|
||||||
onLoad={this.onLoad}
|
|
||||||
onError={this.onError}
|
|
||||||
{...imgData}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
return () => (
|
||||||
return (
|
<div class={bem({ round: props.round })} style={style.value}>
|
||||||
<div
|
{renderImage()}
|
||||||
class={bem({ round: this.round })}
|
{renderPlaceholder()}
|
||||||
style={this.style}
|
{slots.default?.()}
|
||||||
onClick={this.onClick}
|
|
||||||
>
|
|
||||||
{this.genImage()}
|
|
||||||
{this.genPlaceholder()}
|
|
||||||
{this.$slots.default?.()}
|
|
||||||
</div>
|
</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();
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// },
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user