Vue Component Lifecycles & Custom Directives
Understanding the precise sequence of component execution is essential for managing side-effects, interacting with the DOM, and preventing memory leaks. In addition, Vue's custom directives allow developers to hook into lifecycle events of individual DOM elements.
1. What the Interviewer Is Testing
Interviewers use this question to check if you know:
- Mounting Order: Does the parent or child mount first?
- Memory Leak Prevention: How do you clean up timers, event listeners, or WebSockets correctly?
- DOM Access Constraints: In which hook is the template compiled but not yet accessible in the DOM?
- Custom Directive Lifecycle: How do hooks in custom directives map to component lifecycles?
2. The Vue Lifecycle Hooks Sequence
Vue components transition through four core phases: Creation, Mounting, Updating, and Unmounting.
graph TD
A[setup / Creation] --> B[onBeforeMount]
B --> C[onMounted]
C --> D[onBeforeUpdate]
D --> E[onUpdated]
E --> F[onBeforeUnmount]
F --> G[onUnmounted]Parent vs Child Lifecycle Order
A common interview trick is asking about the lifecycle execution sequence when rendering a Parent component containing a Child component.
- Creation & Setup: Parents instantiate first so children can receive props.
Parent setup->Parent onBeforeMount->Child setup->Child onBeforeMount
- Mounting: Children must mount to the DOM before the parent is considered fully mounted.
Child onMounted->Parent onMounted
- Unmounting: The parent begins unmounting first, recursively triggering child unmounting.
Parent onBeforeUnmount->Child onBeforeUnmount->Child onUnmounted->Parent onUnmounted
3. Memory Leak Prevention in onUnmounted
A clean application must release external resources during unmounting. Failing to do so causes JavaScript reference tracking to keep the component in memory, leading to memory leaks.
<script setup>
import { onMounted, onBeforeUnmount } from 'vue'
let socket = null
const handleResize = () => console.log(window.innerWidth)
onMounted(() => {
window.addEventListener('resize', handleResize)
socket = new WebSocket('ws://chat.example.com')
})
onBeforeUnmount(() => {
// Clean up global window events
window.removeEventListener('resize', handleResize)
// Close network sockets
if (socket) socket.close()
})
</script>4. Custom Directives Lifecycles
Custom directives are objects that define hooks to modify elements directly when they enter or update in the DOM.
Writing a Custom Focus Directive
// Registering a custom directive 'v-focus'
const vFocus = {
// Called before bound element's parent component is mounted
created(el, binding, vnode, prevVnode) {},
// Called right before element is inserted into DOM
beforeMount(el) {},
// Called when bound element is mounted to DOM
mounted(el, binding) {
el.focus()
},
// Called before parent component is updated
beforeUpdate(el) {},
// Called after parent component and all children have updated
updated(el) {},
// Called before element is unmounted
beforeUnmount(el) {},
// Called when element is unmounted
unmounted(el) {}
}Custom Directive Arguments & Modifiers
When using <input v-focus:background.lazy="red" />, the directive receives metadata via the binding parameter:
binding.value: The evaluated expression ("red").binding.arg: The argument passed ("background").binding.modifiers: Object showing active modifiers ({ lazy: true }).
