ylj20011123 a289ea61b5 update
2025-09-12 18:08:40 +08:00

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>