#vue #javascript #frontend

Day 6: Lifecycle Hooks & Template Refs

Welcome to Day 6! You know how to create data and update the UI. But sometimes you need to run code at specific moments in time, like when the component first appears.

Lifecycle Hooks

A component comes to life, renders, updates when data changes, and eventually dies (is removed from DOM). We can hook into these moments.

onMounted

Runs when the component is fully inserted into the DOM. This is the place to:

  • Fetch initial data from an API.
  • Focus an input.
  • Initialize 3rd party libraries (like Chart.js).
<script setup lang="ts">
import { onMounted, ref } from 'vue'

const data = ref(null)

onMounted(async () => {
  console.log('Component is ready!')
  data.value = await fetchSomeData()
})
</script>

onUnmounted

Runs when the component is removed (e.g., via v-if="false" or navigating away). Use this to cleanup:

  • clearInterval / clearTimeout
  • Remove window event listeners (window.removeEventListener)
import { onUnmounted } from 'vue'

let intervalId

onMounted(() => {
  intervalId = setInterval(() => { ... }, 1000)
})

onUnmounted(() => {
  clearInterval(intervalId) // Prevent memory leaks!
})

Template Refs

Vue is declarative, so we rarely touch the DOM manually. But sometimes you must (e.g., focusing an input or scrolling a div).

In React, you use useRef. In Vue, we use the ref attribute + a matching variable.

<script setup lang="ts">
import { ref, onMounted } from 'vue'

// 1. Declare a ref with the same name as the ref attribute
const inputElement = ref<HTMLInputElement | null>(null)

onMounted(() => {
  // 2. Access it via .value (it will be assigned after mount)
  inputElement.value?.focus()
})
</script>

<template>
  <input ref="inputElement" />
</template>

Challenge for Day 6

  1. Create a component that displays a “timer” (seconds counting up).
  2. Start the timer (setInterval) when mounted.
  3. Stop the timer (clearInterval) when unmounted.
  4. Add a button “Focus Me” that focuses a specific input field using a Template Ref.

Solution:

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'

const count = ref(0)
const myInput = ref<HTMLInputElement | null>(null)
let timer: number

onMounted(() => {
  timer = setInterval(() => {
    count.value++
  }, 1000)
})

onUnmounted(() => {
  clearInterval(timer)
})

function focusInput() {
  myInput.value?.focus()
}
</script>

<template>
  <p>Timer: {{ count }}</p>
  <input ref="myInput" placeholder="I will be focused" />
  <button @click="focusInput">Focus Me</button>
</template>

You’ve mastered the lifecycle! Tomorrow, we tackle the most important architectural concept: Component Communication (Props & Events).