glhcp/uniapp/components/custom-image/custom-image.vue

152 lines
3.0 KiB
Vue

<template>
<view :style="[viewStyle]" :class="{'custom-image': true, 'image-round': round}" @click="onClick">
<image v-if="!error" :src="src" :mode="mode" :lazy-load="lazyLoad" class="image" :show-menu-by-longpress="showMenuByLongpress"
@load="onLoaded" @error="onErrored"></image>
<view v-if="loading && showLoading" class="loading-wrap image">
<slot v-if="useLoadingSlot" name="loading"></slot>
<u-icon color="#aaa" v-else name="photo-fill" size="45"></u-icon>
</view>
<view v-if="error && showError" class="error-wrap image">
<slot v-if="useErrorSlot" name="error"></slot>
<u-icon color="#aaa" v-else name="error-circle-fill" size="45"></u-icon>
<text class="sm">加载失败</text>
</view>
</view>
</template>
<script>
export default {
props: {
src: {
type: String,
},
round: Boolean,
width: {
type: null
},
height: {
type: null
},
radius: null,
lazyLoad: {
type: Boolean,
default: true
},
useErrorSlot: Boolean,
useLoadingSlot: Boolean,
showMenuByLongpress: Boolean,
mode: {
type: String,
default: 'scaleToFill'
},
showError: {
type: Boolean,
default: true
},
showLoading: {
type: Boolean,
default: true
},
customStyle: {
type: Object,
default: () => {}
}
},
data() {
return {
error: false,
loading: true,
viewStyle: {}
}
},
created() {
this.setStyle();
},
methods: {
setStyle() {
const {
width,
height,
radius
} = this
let style = {};
if (width) {
style.width = width
}
if (height) {
style.height = height
}
if (radius) {
style['overflow'] = 'hidden'
style['border-radius'] = radius
}
this.viewStyle = style;
if(this.customStyle) {
this.viewStyle = Object.assign(this.viewStyle, this.customStyle)
}
},
onLoaded(event) {
this.loading = false
this.$emit('load', event.detail);
},
onErrored(event) {
this.error = false
this.loading = true
this.$emit('error', event.detail);
},
onClick(event) {
this.$emit('click', event.detail);
}
},
watch: {
src() {
this.error = false
this.loading = true
},
width() {
this.setStyle()
},
height() {
this.setStyle()
}
}
}
</script>
<style lang="scss">
.custom-image {
position: relative;
display: block;
width: 100%;
height: 100%;
&.image-round {
overflow: hidden;
border-radius: 50%;
}
.image {
display: block;
width: 100%;
height: 100%;
}
.loading-wrap,
.error-wrap {
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #969799;
font-size: 28rpx;
background-color: #f7f8fa;
}
}
</style>