Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 1x | <template>
<div v-if="!loaded" class="lazy-placeholder" data-testid="lazy-placeholder" aria-hidden="true" />
<img
:id="id"
loading="lazy"
:src="./error || !src ? defaultLogo : src"
:alt="alt"
ref="imgRef"
:class="clsx('img-fluid', className ?? '', { lazyloaded: loaded, lazyloading: !loaded })"
@load="onLoad"
@error="onError"
@click="onClick"
/>
</template>
<script setup lang="ts">
import { clsx } from 'clsx';
import { onMounted, onUnmounted, ref } from 'vue';
defineProps<{
id?: string;
className?: string;
src?: string | null;
alt?: string;
onClick?: () => void;
}>();
const defaultLogo = 'https://upload.wikimedia.org/wikipedia/commons/a/ac/No_image_available.svg';
const loaded = ref(false);
const error = ref(false);
const imgRef = ref<HTMLImageElement | null>(null);
function onLoad() {
loaded.value = true;
}
function onError() {
error.value = true;
}
onMounted(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
observer.disconnect();
}
},
{ threshold: 0.1 }
);
if (imgRef.value) observer.observe(imgRef.value);
onUnmounted(() => observer.disconnect());
});
</script>
<style scoped src="././LazyImage.scss" />
|