125 lines
2.3 KiB
Vue
125 lines
2.3 KiB
Vue
<!-- src/components/itemCenter.vue -->
|
||
<template>
|
||
<div style="position: relative; width: 100%" ref="containerRef">
|
||
<!-- 背景图 -->
|
||
<img
|
||
v-if="shouldShowImage"
|
||
v-smart-img
|
||
:src="imgUrl"
|
||
alt=""
|
||
width="100%"
|
||
style="display: block"
|
||
:crossorigin="isOSSImage ? 'anonymous' : undefined"
|
||
/>
|
||
<div
|
||
v-else
|
||
class="placeholder"
|
||
:style="{
|
||
width: '100%',
|
||
height: '100%',
|
||
backgroundColor: '#f0f0f0',
|
||
}"
|
||
></div>
|
||
|
||
<!-- 内容 -->
|
||
<div
|
||
class="scrollY"
|
||
style="
|
||
position: absolute;
|
||
inset: 0;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
"
|
||
:style="contentStyle"
|
||
>
|
||
<slot></slot>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted, computed } from 'vue'
|
||
|
||
const props = defineProps({
|
||
imgUrl: {
|
||
type: String,
|
||
default: '',
|
||
required: true,
|
||
},
|
||
|
||
contentStyle: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
|
||
// 是否启用懒加载
|
||
lazy: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
|
||
// 是否立即显示(优先级高于lazy)
|
||
immediate: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
})
|
||
|
||
const containerRef = ref(null)
|
||
const isVisible = ref(false)
|
||
|
||
// 是否应该显示图片
|
||
const shouldShowImage = computed(() => {
|
||
// 如果标记为立即显示或禁用懒加载,则直接显示
|
||
if (props.immediate || !props.lazy) {
|
||
return true
|
||
}
|
||
|
||
// 否则根据是否可见决定
|
||
return isVisible.value
|
||
})
|
||
|
||
// 判断是否为OSS图片
|
||
const isOSSImage = computed(() => {
|
||
return props.imgUrl.startsWith('https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5')
|
||
})
|
||
|
||
// 创建交叉观察器
|
||
const createObserver = () => {
|
||
if (!props.lazy || props.immediate) return
|
||
|
||
if (!containerRef.value) return
|
||
|
||
const observer = new IntersectionObserver(
|
||
(entries) => {
|
||
entries.forEach((entry) => {
|
||
if (entry.isIntersecting) {
|
||
isVisible.value = true
|
||
observer.unobserve(entry.target)
|
||
}
|
||
})
|
||
},
|
||
{
|
||
rootMargin: '100px', // 提前100px开始加载
|
||
}
|
||
)
|
||
|
||
observer.observe(containerRef.value)
|
||
}
|
||
|
||
onMounted(() => {
|
||
createObserver()
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.placeholder {
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
|
||
.scrollY::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
</style>
|