90 lines
1.6 KiB
Vue
90 lines
1.6 KiB
Vue
<!--
|
||
@name: LazyImage
|
||
@author: kahu4
|
||
@date: 2023-11-16 18:38
|
||
@description:图片懒加载
|
||
@update: 2023-11-16 18:38
|
||
-->
|
||
<script setup>
|
||
import { getCurrentInstance, nextTick, onMounted, ref, toRefs } from "vue";
|
||
import { lazyLoading } from "@/utils/images";
|
||
|
||
/**
|
||
* @property {string|number} 图片的唯一标识 必填(要求和lazy-${id})
|
||
*/
|
||
const props = defineProps({
|
||
unique: {
|
||
type: [String, Number],
|
||
required: true
|
||
},
|
||
src: {
|
||
type: String,
|
||
required: true
|
||
},
|
||
mode: {
|
||
type: String
|
||
}
|
||
})
|
||
const {
|
||
unique,
|
||
src,
|
||
mode
|
||
} = toRefs(props)
|
||
|
||
const showTruePic = ref(false); // 是否展示真是地址
|
||
|
||
const _this = getCurrentInstance()
|
||
|
||
function observerImage() {
|
||
const intersectionObserver = uni.createIntersectionObserver(_this);
|
||
intersectionObserver.relativeToViewport()
|
||
intersectionObserver.observe(`.lazy-${ unique.value }`, (res) => {
|
||
if (res.intersectionRatio <= 0) return
|
||
showTruePic.value = true
|
||
})
|
||
}
|
||
|
||
onMounted(() => {
|
||
nextTick(observerImage);
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<view :class="['lazy-image']">
|
||
<view :class="[`lazy-${unique}`,'lazy-image__inner']">
|
||
<image
|
||
v-if="showTruePic"
|
||
class="image-context"
|
||
:src="src"
|
||
:mode="mode"
|
||
/>
|
||
<image
|
||
class="image-context"
|
||
:src="lazyLoading"
|
||
v-else
|
||
/>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<style
|
||
scoped
|
||
lang="scss"
|
||
>
|
||
.lazy-image {
|
||
// 微信小程序不设置这个会炸裂
|
||
width: 100%;
|
||
height: 100%;
|
||
|
||
&__inner {
|
||
width: 100%;
|
||
height: 100%;
|
||
|
||
.image-context {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
}
|
||
</style>
|