1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["a/useIntersection.r.js","a/rolldown-runtime.js","a/v.js","a/q.js","a/q.css","a/AppFullscreen.r.js","a/useIntersection.css","a/useIntersection.s.js"])))=>i.map(i=>d[i]); 2import{H as e,T as t,U as n,Z as r,ft as i,p as a,v as o,w as s,y as c}from"./v.js";import{a as l}from"./index.js";import{t as u}from"./DocCode.js";import"./DocCopyBtn.js";import{t as d}from"./page-utils.js";import{t as f}from"./DocPage.js";import{t as p}from"./DocLink.js";import{t as m}from"./DocPrerender.js";import{t as h}from"./DocExample.js";var g={__name:`use-intersection`,setup(g){n(`_q_ex`,{name:`useIntersection`,runtime:l(()=>import(`./useIntersection.r.js`).then(e=>e.t),__vite__mapDeps([0,1,2,3,4,5,6])),source:()=>l(()=>import(`./useIntersection.s.js`).then(e=>e.t),__vite__mapDeps([7,1]))});let _=[{name:`Intersection`,category:`Vue Components`,path:`/vue-components/intersection`},{name:`v-intersection`,category:`Vue Directives`,path:`/vue-directives/intersection`}],v=[{name:`useEventListener`,category:`Vue Composables`,path:`/vue-composables/use-event-listener`,classes:`doc-page__related--left`},{name:`useKeyboardShortcut`,category:`Vue Composables`,path:`/vue-composables/use-keyboard-shortcut`,classes:`doc-page__related--right`}],y=[{id:`syntax`,title:`2. Syntax`},{id:`changing-the-options-while-running`,title:`3. Changing the options while running`},{id:`example`,title:`4. Example`}];return(n,l)=>(e(),c(f,{title:`useIntersection composable`,desc:`What is useIntersection() composable and how you can use it`,badge:`v2.30+`,heading:``,"edit-link":`vue-composables/use-intersection`,"md-link":``,toc:y,related:_,nav:v},{default:r(()=>[o(`p`,null,[l[7]||=s(`The `,-1),l[8]||=o(`code`,{class:`doc-token`},`useIntersection()`,-1),l[9]||=s(` composable tells you whether an element is visible on screen (or inside a scrolling parent), through a reactive Boolean. Under the hood it uses the `,-1),t(p,{to:`https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API`},{default:r(()=>[...l[6]||=[s(`Intersection Observer API`,-1)]]),_:1}),l[10]||=s(`.`,-1)]),o(`p`,null,[l[13]||=s(`It is the setup-code counterpart of the `,-1),t(p,{to:`/vue-directives/intersection`},{default:r(()=>[...l[11]||=[s(`Intersection directive`,-1)]]),_:1}),l[14]||=s(` and of the `,-1),t(p,{to:`/vue-components/intersection`},{default:r(()=>[...l[12]||=[s(`QIntersection`,-1)]]),_:1}),l[15]||=s(` component: all three share one Intersection Observer per configuration, so observing many elements stays cheap to
2scroll. Use the composable when you want the state on your component or on any element or component ref, without wrapping it in an extra DOM element.`,-1)]),l[19]||=o(`div`,{class:`doc-note doc-note--note`},[o(`div`,{class:`doc-note__title`},`NOTE`),o(`p`,null,[s(`On the server-side of SSR or SSG modes, the composable never observes anything: `),o(`code`,{class:`doc-token`},`isIntersecting`),s(` stays `),o(`code`,{class:`doc-token`},`false`),s(` until the client takes over.`)])],-1),l[20]||=o(`div`,{class:`doc-note doc-note--tip`},[o(`div`,{class:`doc-note__title`},`Outside of a component`),o(`p`,null,[s(`The composable can also be called outside of `),o(`code`,{class:`doc-token`},`setup()`),s(`: in a boot file, a store or a plain module. There is no component root to fall back on and no mount to wait for, so supply a `),o(`code`,{class:`doc-token`},`target`),s(` (an element, or a ref or getter of one); the observation starts right away and nothing stops it by itself: call `),o(`code`,{class:`doc-token`},`stopIntersection()`),s(` when you are done.`)])],-1),o(`h2`,{id:`syntax`,class:`doc-heading doc-h2`,onClick:l[1]||=e=>i(d)(`syntax`)},[l[16]||=s(`Syntax`,-1),o(`a`,{class:`doc-heading__anchor`,href:`#syntax`,"aria-label":`Copy anchor to Syntax`,onClick:l[0]||=a(e=>i(d)(`syntax`),[`prevent`,`stop`])})]),t(i(m),null,{default:r(()=>[t(u,{lang:`js`,code:`import { useTemplateRef } from 'vue' 3import { useIntersection } from 'quasar' 4 5setup () { 6 const target = useTemplateRef('target') // an Element or a component 7 8 const { isIntersecting, refreshIntersection, stopIntersection } = useIntersection({ 9 // all optional: 10 target, // (default: the component's own root element) 11 root: null, // Element used as viewport (default: null, the browser viewport) 12 rootMargin: '10px', // CSS-like margin around the root (default: '0px') 13 threshold: 0.5, // Number or Array of Numbers, 0 to 1 (default: 0) 14 once: true, // stop observing after the first time the target is visible (default: false) 15 disabled: true, // pause observing (default: false) 16 onIntersect (entry) { // called with every IntersectionObserverEntry 17 // return false to stop observing 18 } 19 }) 20 21 // ... 22}`})]),_:1}),t(i(m),null,{default:r(()=>[t(u,{lang:`ts`,code:`function useIntersection( 23 options?: MaybeRefOrGetter<{ 24 target?: MaybeRefOrGetter< 25 Element | ComponentPublicInstance | null | undefined 26 > 27 root?: Element | Document | null 28 rootMargin?: string 29 threshold?: number | number[] 30 once?: boolean 31 disabled?: boolean 32 onIntersect?: (entry: IntersectionObserverEntry) => false | void 33 }> 34): { 35 isIntersecting: Ref<boolean> 36 refreshIntersection: () => void 37 stopIntersection: () => void 38}`})]),_:1}),l[21]||=o(`p`,null,[s(`Without a `),o(`code`,{class:`doc-token`},`target`),s(`, the composable observes the root element of the component it is called in, as of the moment the component gets mounted. A component rendering a fragment (multiple root nodes) has no root element to observe, so supply a `),o(`code`,{class:`doc-token`},`target`),s(` there.`)],-1),l[22]||=o(`p`,null,[o(`code`,{class:`doc-token`},`refreshIntersection()`),s(` makes the observer report the current state again, whether it changed or not (it does nothing while `),o(`code`,{class:`doc-token`},`disabled`),s(` or before the target exists). An observer only reports changes on its own, so this is for the cases where your code needs a fresh verdict after doing something to the layout, such as knowing whether a target that was in view still is after the content around it grew.`)],-1),l[23]||=o(`p`,null,[o(`code`,{class:`doc-token`},`stopIntersection()`),s(` ends the observation for good. You will rarely need it, as the composable stops by itself when the component gets destroyed.`)],-1),o(`h2`,{id:`changing-the-options-while-running`,class:`doc-heading doc-h2`,onClick:l[3]||=e=>i(d)(`changing-the-options-while-running`)},[l[17]||=s(`Changing the options while running`,-1),o(`a`,{class:`doc-heading__anchor`,href:`#changing-the-options-while-running`,"aria-label":`Copy anchor to Changing the options while running`,onClick:l[2]||=a(e=>i(d)(`changing-the-options-while-running`),[`prevent`,`stop`])})]),l[24]||=o(`p`,null,`The options can be a plain Object, a Ref or a getter Function. A plain Object is read once. With a Ref or a getter, the composable tracks whatever reactive state the options read and re-applies them whenever that state changes, so you never call anything to âupdateâ it:`,-1),l[25]||=o(`ul`,null,[o(`li`,null,[s(`toggling `),o(`code`,{class:`doc-token`},`disabled`),s(` pauses and resumes the observation (`),o(`code`,{class:`doc-token`},`isIntersecting`),s(` keeps its last value while paused)`)]),o(`li`,null,[s(`changing `),o(`code`,{class:`doc-token`},`root`),s(`, `),o(`code`,{class:`doc-token`},`rootMargin`),s(` or `),o(`code`,{class:`doc-token`},`threshold`),s(` moves the target to an observer with the new configuration`)]),o(`li`,null,[s(`pointing `),o(`code`,{class:`doc-token`},`target`),s(` to another element (or letting a template ref change through `),o(`code`,{class:`doc-token`},`v-if`),s(`) follows it`)]),o(`li`,null,[s(`swapping `),o(`code`,{class:`doc-token`},`onIntersect`),s(` takes effect from the next entry`)])],-1),l[26]||=o(`p`,null,`Options that resolve to the same values are a no-op, so a getter that rebuilds the Object on every run costs nothing extra.`,-1),t(i(m),null,{default:r(()=>[t(u,{lang:`js`,code:`import { ref } from 'vue' 39import { useIntersection } from 'quasar' 40 41setup () { 42 const paused = ref(false) 43 const threshold = ref(0) 44 45 const { isIntersecting } = useIntersection(() => ({ 46 disabled: paused.value, 47 threshold: threshold.value 48 })) 49 50 function pause () { paused.value = true } 51 function resume () { paused.value = false } 52 53 // from now on the handler fires only when at least 54 // half of the element is visible 55 function requireHalf () { threshold.value = 0.5 } 56 57 // ... 58}`})]),_:1}),l[27]||=o(`p`,null,`The same works with a Ref holding the whole options Object:`,-1),t(i(m),null,{default:r(()=>[t(u,{lang:`js`,code:`const options = ref({ rootMargin: '0px' }) 59 60const { isIntersecting } = useIntersection(options) 61 62// later on 63options.value = { rootMargin: '200px' }`})]),_:1}),l[28]||=o(`p`,null,[s(`A `),o(`code`,{class:`doc-token`},`once`),s(` observation that has already fired stays off for as long as `),o(`code`,{class:`doc-token`},`once`),s(` holds: toggling `),o(`code`,{class:`doc-token`},`disabled`),s(` or changing any other option does not start observing again. Setting `),o(`code`,{class:`doc-token`},`once`),s(` back to `),o(`code`,{class:`doc-token`},`false`),s(` does, and the observation can retire again the next time `),o(`code`,{class:`doc-token`},`once`),s(` is turned on. An `),o(`code`,{class:`doc-token`},`onIntersect`),s(` hook that returned `),o(`code`,{class:`doc-token`},`false`),s(`, or a call to `),o(`code`,{class:`doc-token`},`stopIntersection()`),s(`, ends the observation for good.`)],-1),o(`h2`,{id:`example`,class:`doc-heading doc-h2`,onClick:l[5]||=e=>i(d)(`example`)},[l[18]||=s(`Example`,-1),o(`a`,{class:`doc-heading__anchor`,href:`#example`,"aria-label":`Copy anchor to Ex
63ample`,onClick:l[4]||=a(e=>i(d)(`example`),[`prevent`,`stop`])})]),l[29]||=o(`p`,null,[s(`The card below is observed through a template ref, with the scrolling box as `),o(`code`,{class:`doc-token`},`root`),s(` and a list of thresholds so that the `),o(`code`,{class:`doc-token`},`onIntersect`),s(` hook reports the visible ratio. Toggle `),o(`code`,{class:`doc-token`},`once`),s(` to stop observing after the next time the card is in view, and toggle it back off to observe again:`)],-1),t(h,{title:`Observing an element`,file:`Basic`}),l[30]||=o(`p`,null,[s(`To observe the componentâs own root element instead, omit the `),o(`code`,{class:`doc-token`},`target`),s(`. The card below starts loading its image a bit before it enters the viewport and, thanks to `),o(`code`,{class:`doc-token`},`once`),s(`, is not observed anymore after that:`)],-1),t(i(m),null,{default:r(()=>[t(u,{lang:`html`,code:`<template> 64 <div class="card"> 65 <img v-if="isIntersecting" :src="src" /> 66 </div> 67</template> 68 69<script setup> 70 import { useIntersection } from 'quasar' 71 72 defineProps({ src: String }) 73 74 // observes this component's root element (the card) 75 const { isIntersecting } = useIntersection({ 76 rootMargin: '200px', 77 once: true 78 }) 79<\/script>`})]),_:1})]),_:1}))}};export{g as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.