import IntersectionObserverProvider from "@wikicasa-dev/components/generic/IntersectionObserver/v2/IntersectionObserverProvider";
Renderless wrapper that creates one browser IntersectionObserver (viewport as root) and shares it with every IntersectionObserverTarget inside it. Each target gets its own isVisible flag. Use the pair to:
- render a heavy section (chart, map, carousel, list of cards) only when it scrolls into view;
- run something when a sentinel becomes visible (infinite scroll: "load more" when the last row appears), via the provider's
intersectionevent.
This replaces the older IntersectionObserver + IntersectionObservable pair.
Usage
Lazy section plus an infinite-scroll sentinel:
<script setup lang="ts">
import { ref } from "vue";
import IntersectionObserverProvider from "@wikicasa-dev/components/generic/IntersectionObserver/v2/IntersectionObserverProvider";
import IntersectionObserverTarget from "@wikicasa-dev/components/generic/IntersectionObserver/v2/IntersectionObserverTarget";
const listings = ref(["Bilocale a Bari", "Villa a Lecce", "Attico a Taranto"]);
const loadMore = () => listings.value.push(`Annuncio ${listings.value.length + 1}`);
</script>
<template>
<IntersectionObserverProvider :threshold="0.1">
<IntersectionObserverTarget v-slot="{ isVisible }">
<section v-if="isVisible">Andamento prezzi a Bari (grafico)</section>
<div v-else style="height: 270px" />
</IntersectionObserverTarget>
</IntersectionObserverProvider>
<ul>
<li v-for="l in listings" :key="l">{{ l }}</li>
</ul>
<IntersectionObserverProvider @intersection="loadMore">
<IntersectionObserverTarget :observe-once="false">
<p>Caricamento altri annunci…</p>
</IntersectionObserverTarget>
</IntersectionObserverProvider>
</template>
Do / Don't
- Do put every
IntersectionObserverTargetinside a provider; outside one,isVisiblestaysfalseforever. - Do reserve the final height in the not-visible branch so the page doesn't jump when content appears.
intersectionfires every time any target enters the viewport (repeatedly for targets with:observe-once="false").- Use
emit-onceonly with a single target: it disconnects the whole observer after the first intersection, so other targets never become visible. - Don't use
skipto "show everything immediately": it ignores all intersections, so targets never become visible. To bypass lazy rendering, render your content without the provider (e.g.v-if="!lazy"/v-else). threshold(0–1, share of the target that must be visible) is read once, when the provider is created.- Observation runs only in the browser: on the server every target renders its not-visible branch.
API
Generated from the component's types. Do not edit by hand.
Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
emitOnce |
boolean |
false |
||
skip |
boolean |
false |
||
threshold |
number |
0 |
Events
| Name | Payload |
|---|---|
intersection |
v-model
None.
Slots
| Name | Slot props |
|---|---|
default |
{ observer: IntersectionObserver | undefined; } |
Exposed (template ref)
None.