Vue JS Lifecycle Hooks 2 — Questions and Answers
Question 1: In Vue 3 Composition API, what replaces the `beforeCreate` and `created` Options API hooks?
- The setup() function itself — code in setup() runs at the same time as these hooks (Correct answer)
- onSetup()
- onCreated()
- There is no equivalent
Correct answer: The setup() function itself — code in setup() runs at the same time as these hooks
In Composition API, the `setup()` function runs synchronously when the component instance is created, replacing both `beforeCreate` and `created`. Code placed at the top of `setup()` effectively runs at creation time.
Vue 3's Composition API does not expose `onBeforeCreate` or `onCreated` hooks because `setup()` is called right after `beforeCreate` and before `created` in the lifecycle. Any initialization code you need runs synchronously at the top of `setup()`. The Vue 3 documentation recommends simply placing `created` logic directly in `setup()`. This simplification reduces the number of hooks to remember and makes setup intent clearer.
Question 2: When does `onUpdated` fire and what should you avoid doing inside it?
- After the component re-renders due to state/prop changes; avoid mutating state inside it to prevent infinite loops (Correct answer)
- After every animation frame
- When child components update, not the current component
- After the component's watch callbacks run
Correct answer: After the component re-renders due to state/prop changes; avoid mutating state inside it to prevent infinite loops
`onUpdated` fires after the DOM is patched due to a reactive state change. Mutating reactive state inside it can trigger another update, potentially causing infinite loops.
`onUpdated` fires after every re-render triggered by reactive state or prop changes. It's useful for operating on the updated DOM (e.g., re-initializing a third-party library after content changes). However, you must NOT mutate component state inside `onUpdated` unconditionally — this would trigger another render, which fires `onUpdated` again, creating an infinite loop. If you need to react to specific state changes, use `watch` instead. Also: `onUpdated` fires for any update, not just specific data changes — use `watch` for targeted reactions.
Question 3: What does `nextTick` do in Vue 3 and when would you use it?
- Waits for the next DOM update flush, then runs the callback — use after data changes when you need the updated DOM (Correct answer)
- Delays code execution to the next JavaScript event loop tick
- Batches multiple reactive updates into one render
- Schedules a component re-render
Correct answer: Waits for the next DOM update flush, then runs the callback — use after data changes when you need the updated DOM
`nextTick` schedules code to run after Vue flushes pending DOM updates, ensuring you're working with the updated DOM when you need to read layout or measurements after a state change.
Vue batches DOM updates asynchronously. When you set `count.value = 10`, the DOM isn't updated immediately — it queues a flush. `await nextTick()` (or `nextTick(callback)`) defers execution until after that flush. Common use case: after setting `showModal.value = true`, you need to focus an element inside the modal. Since the modal isn't in the DOM yet when you set the flag, you do: `showModal.value = true; await nextTick(); modalInput.value.focus()`. `nextTick` returns a Promise, making it work naturally with async/await.
Question 4: In Vue 3, how do you access a template ref (DOM element) inside a lifecycle hook?
- Declare const myEl = ref(null), add ref="myEl" to the element, then access myEl.value inside onMounted
- Use document.getElementById in setup()
- Use this.$refs.myEl in Options API or useTemplateRef() in Composition API
- Both A and C are correct (Correct answer)
Correct answer: Both A and C are correct
Template refs are accessed in Composition API via a `ref(null)` matched to a `ref="name"` attribute, available in `onMounted`. In Options API, `this.$refs` is the equivalent. Both are valid in Vue 3.
In `<script setup>`: `const input = ref(null)` + `<input ref="input" />`. After `onMounted`, `input.value` is the DOM element. Vue 3.5+ introduced `useTemplateRef('refName')` as an explicit API. In Options API: `<input ref="myInput" />` is accessed as `this.$refs.myInput` inside lifecycle hooks. Template refs are populated only after `onMounted` — in `setup()` or `onBeforeMount`, they're still null. For component refs, the value is the component's public instance (or what's exposed via `defineExpose`).
Question 5: What is the difference between `onMounted` and `onBeforeMount` in Vue 3?
- `onBeforeMount` fires before DOM insertion (no $el yet); `onMounted` fires after the component and children are fully in the DOM (Correct answer)
- They fire at the same time but in different order
- `onBeforeMount` is for parent components; `onMounted` is for child components
- `onBeforeMount` receives the virtual DOM; `onMounted` receives the real DOM
Correct answer: `onBeforeMount` fires before DOM insertion (no $el yet); `onMounted` fires after the component and children are fully in the DOM
`onBeforeMount` fires right before the first render inserts the DOM. The component's reactive state is set up but the DOM doesn't exist yet. `onMounted` fires after the DOM is fully inserted.
At `onBeforeMount` time: the component template has been compiled, reactive state is initialized, but no DOM nodes exist for this component. Using `$el` or template refs here returns null. At `onMounted` time: the component's root DOM element exists, template refs are populated, and all synchronous child components are also mounted. The vast majority of use cases need `onMounted`. `onBeforeMount` is rarely needed — one use case is measuring something in the parent before the child's DOM is inserted.
Question 6: How does the lifecycle of a component inside `<KeepAlive>` differ from a normal component?
- `onMounted`/`onUnmounted` fire only once; `onActivated`/`onDeactivated` fire on each show/hide cycle (Correct answer)
- No difference — all hooks fire normally
- `onMounted` fires every time the component is shown
- KeepAlive disables all lifecycle hooks
Correct answer: `onMounted`/`onUnmounted` fire only once; `onActivated`/`onDeactivated` fire on each show/hide cycle
Inside `<KeepAlive>`, the component is cached rather than destroyed on hide. `onMounted` fires once on initial mount and `onUnmounted` fires only when the cache is cleared. `onActivated`/`onDeactivated` replace the show/hide cycle.
Normal component lifecycle: mount → (updates) → unmount, repeating if the component is shown/hidden via v-if or router navigation. With `<KeepAlive>`: mount fires once → deactivate fires when hidden (cached) → activate fires when shown again → unmount fires only when the cache is cleared (e.g., navigating away and the cache limit is exceeded). This means data initialized in `onMounted` persists across activations. Use `onActivated` to refresh data that might be stale from the cache. `max` prop controls cache size; `include`/`exclude` props filter which components to cache.
In Vue 3 Composition API, what replaces the `beforeCreate` and `created` Options API hooks?