Foresight component
Foresight is the component form of useForesight: one instance, one registration. It renders in one of two ways.
Rendering an element with as
With as, Foresight renders that element itself and registers it.
<script setup lang="ts">
import { Foresight } from "@foresightjs/vue"
</script>
<template>
<Foresight as="button" :callback="() => prefetch('/checkout')" @click="checkout">
Checkout
</Foresight>
</template>
as accepts any element tag ("button", "a", "div", ...) or a component whose root is a DOM element.
In the as form there is no way to pass your own ref to the rendered element, Foresight uses the ref slot for its registration. If you need the DOM node, use the render-prop form below and attach both refs yourself.
Styling with data attributes
In the as form, Foresight mirrors the element state onto data attributes — by mutating the DOM directly, without re-rendering the component:
data-predicted— present whileisPredictedis truedata-callback-running— present while the callback is executingdata-status—"success"or"error"after the last callback run
This makes prediction styling pure CSS:
button[data-predicted] {
outline: 1px solid orange;
}
Or with Tailwind:
<Foresight as="button" :callback="() => prefetch('/checkout')" class="data-predicted:outline-1">
Checkout
</Foresight>
Reading state in as form
To use the reactive state in this form, read it from the scoped default slot:
<Foresight as="button" :callback="() => prefetch('/checkout')" #default="{ isCallbackRunning }">
{{ isCallbackRunning ? "Prefetching…" : "Checkout" }}
</Foresight>
Render-prop form
Without as, Foresight renders only its default slot. The scoped slot receives the reactive state plus the elementRef to attach, which gives full control over the markup:
<script setup lang="ts">
import { Foresight } from "@foresightjs/vue"
</script>
<template>
<Foresight
foresight-name="checkout"
:callback="() => prefetch('/checkout')"
#default="{ elementRef, isPredicted }"
>
<button :ref="elementRef" :class="{ predicted: isPredicted }">Checkout</button>
</Foresight>
</template>
You must bind elementRef to an element with :ref="elementRef", without it nothing is registered with Foresight.
Options
Foresight takes the same options as useForesight, passed as props. The only renamed option is name, on the component it is foresightName, so the HTML name attribute (on input, button, select, ...) falls through to the element like any other attribute.
Dynamic lists
Foresight can be rendered in a v-for, registering one element per item:
<script setup lang="ts">
import { Foresight } from "@foresightjs/vue"
const links = [
{ href: "/about", label: "About" },
{ href: "/contact", label: "Contact" },
]
</script>
<template>
<nav>
<Foresight
v-for="link in links"
:key="link.href"
as="a"
:href="link.href"
:foresight-name="link.label"
:callback="() => prefetch(link.href)"
>
{{ link.label }}
</Foresight>
</nav>
</template>