102 lines
2.4 KiB
Vue
102 lines
2.4 KiB
Vue
<template>
|
|
<view class="lazy-image-wrapper" :style="{ width: width, height: height }">
|
|
<image :src="optimizedSrc" :style="{ width: width, height: height, opacity: imageLoaded ? 1 : 0 }" :mode="mode"
|
|
@load="onImageLoad" @error="onImageError" :lazy-load="false" :show-menu-by-longpress="false" />
|
|
<view v-if="!imageLoaded && !showError" class="placeholder">
|
|
<view class="loading-bg"></view>
|
|
</view>
|
|
<view v-if="showError" class="error-placeholder">
|
|
<image src="/static/images/home/defaultIcon.png" :style="{ width: width, height: height }" :mode="mode" />
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
props: {
|
|
src: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
width: {
|
|
type: String,
|
|
default: '100%'
|
|
},
|
|
height: {
|
|
type: String,
|
|
default: '100%'
|
|
},
|
|
mode: {
|
|
type: String,
|
|
default: 'aspectFill'
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
imageLoaded: false,
|
|
showError: false
|
|
}
|
|
},
|
|
computed: {
|
|
optimizedSrc() {
|
|
// 直接返回原图,避免无效参数
|
|
return this.src || ''
|
|
}
|
|
},
|
|
methods: {
|
|
onImageLoad() {
|
|
this.imageLoaded = true
|
|
this.showError = false
|
|
},
|
|
onImageError() {
|
|
this.showError = true
|
|
this.imageLoaded = false
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.lazy-image-wrapper {
|
|
position: relative;
|
|
overflow: hidden;
|
|
|
|
.placeholder {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background-color: #f5f5f5;
|
|
z-index: 1;
|
|
|
|
.loading-bg {
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: #f0f0f0;
|
|
border-radius: 4rpx;
|
|
}
|
|
}
|
|
|
|
.error-placeholder {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background-color: #f5f5f5;
|
|
z-index: 2;
|
|
}
|
|
|
|
image {
|
|
display: block;
|
|
transition: opacity 0.2s;
|
|
}
|
|
}
|
|
</style> |