All quizzesHard
Advanced Rendering Techniques — Series 2
Preview — 3 of 10 questions
Why does wrapping precomputeSearchIndex() in requestIdleCallback avoid competing with the component's initial render?
javascript
<script setup>
import { onMounted } from 'vue'
function precomputeSearchIndex() {
// expensive: builds a search index over thousands of records,
// not needed until the user actually opens the search box
}
onMounted(() => {
if ('requestIdleCallback' in window) {
requestIdleCallback(() => precomputeSearchIndex())
} else {
setTimeout(precomputeSearchIndex, 1) // fallback for browsers without it
}
})
</script>ArequestIdleCallback schedules its callback to run during a browser idle period — after the browser has finished more urgent work (rendering, responding to user input, running other higher-priority tasks) for the current frame — so an expensive, non-urgent computation like building a search index doesn't compete with, and potentially delay, the actually-visible initial paint and interactivity the user is waiting for
BrequestIdleCallback runs its callback immediately and synchronously — this code is functionally identical to calling precomputeSearchIndex() directly inside onMounted
CrequestIdleCallback is a Vue-specific API for scheduling low-priority reactive effects — it has no meaning outside of a Vue application
DrequestIdleCallback guarantees the callback runs within 1 second, no matter what — it's purely a maximum-delay guarantee, unrelated to browser idle time
How does this differ from using IntersectionObserver for lazy-loading images?
javascript
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const sectionRefs = ref([])
let observer
onMounted(() => {
observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('fade-in-visible')
}
})
},
{ threshold: 0.2 }
)
sectionRefs.value.forEach((el) => observer.observe(el))
})
onUnmounted(() => observer?.disconnect())
</script>
<template>
<section v-for="section in sections" :key="section.id" ref="sectionRefs" class="fade-in">
{{ section.content }}
</section>
</template>AHere, IntersectionObserver isn't deferring any network resource at all — it's purely triggering a CSS class toggle (fade-in-visible) the moment an already-rendered element scrolls into the viewport, to kick off a scroll-triggered reveal animation. This is a genuinely different use case from image lazy-loading (which defers fetching), even though both rely on the same underlying browser API for "tell me when this element becomes visible"
BThis is functionally identical to the lazy-image-loading use case — both simply defer fetching a resource until the element scrolls into view, and this example is just a stylistic variation with no real difference in purpose
CIntersectionObserver cannot be used for anything other than lazy-loading images and iframes — using it to toggle a CSS class, as shown, silently does nothing
Dthreshold: 0.2 means the callback fires when the element is 0.2 pixels away from the viewport — it's a pixel-based distance, not a visibility-ratio setting
For a form with 50+ fields, why might a single reactive() object cause more unnecessary re-render work than individually-tracked refs, when only one field changes?
javascript
// Approach A: one big reactive object
const formData = reactive({
firstName: '', lastName: '', email: '', /* ... 47 more fields ... */
})
// Approach B: individual refs per field
const firstName = ref('')
const lastName = ref('')
const email = ref('')
// ... 47 more individual refs ...ANeither approach has any meaningful difference — Vue's reactivity tracks every property access with the same granularity regardless of how the fields are grouped
BApproach A is always better for large forms, since it requires writing far less boilerplate than declaring 50 individual refs
CA component or computed that reads formData.firstName specifically only depends on that one property — Vue's Proxy-based reactivity for reactive() objects already tracks individual property access, not the whole object as one unit, so a change to formData.email does NOT cause something that only reads formData.firstName to re-evaluate. The actual difference between the two approaches is mostly about destructuring ergonomics (a reactive() object's properties lose reactivity if destructured directly, requiring toRefs, covered elsewhere in this series) rather than a meaningful re-render granularity difference — both approaches offer comparably fine-grained tracking when used correctly
DApproach B is objectively wrong for forms — v-model can only bind to properties of a single reactive() object, never to standalone individual refs
Sign up free to play
Answer all 10 questions (7 more), see explanations for every answer, and track your score.