VuVue · Lesson 2 of 7

Reactivity: ref & reactive

Vue's reactivity system tracks which data a template uses and only re-renders what changed. `ref` wraps a primitive. `reactive` wraps an object. Know the difference and you'll avoid 90% of Vue gotchas.

HTML
<template>
  <div>
    <!-- Access ref values with .value in <script>, directly in template -->
    <p>Count: {{ count }}</p>
    <p>Name: {{ name }}</p>
    <p>Items: {{ items.join(', ') }}</p>
    <button @click="increment">+</button>
    <button @click="addItem">Add Item</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

// ref() — for primitives (number, string, boolean) and anything you might reassign
const count = ref(0)
const name  = ref("Alice")
const items = ref([])

// In <script>, access the value with .value
function increment() {
  count.value++
}

function addItem() {
  items.value.push(`Item ${items.value.length + 1}`)
}

// You can reassign refs entirely
function reset() {
  count.value = 0
  items.value = []   // OK — reassigning the ref
}
</script>
HTML
<template>
  <form @submit.prevent="submit">
    <input v-model="form.name"  placeholder="Name" />
    <input v-model="form.email" placeholder="Email" type="email" />
    <button type="submit">Submit</button>
    <pre>{{ form }}</pre>
  </form>
</template>

<script setup>
import { reactive, computed, watch } from 'vue'

// reactive() — for objects (no .value needed)
const form = reactive({
  name:  "",
  email: "",
})

// computed() — derived reactive value, cached
const isValid = computed(() =>
  form.name.length > 0 && form.email.includes("@")
)

// watch() — run a function when a value changes
watch(() => form.email, (newEmail) => {
  console.log("Email changed to:", newEmail)
})

function submit() {
  if (!isValid.value) return alert("Invalid form")
  console.log("Submitting:", { ...form })
  form.name  = ""
  form.email = ""
}
</script>
✦ Tip
Rule of thumb: use `ref` for single values (number, string, array you'll replace), `reactive` for objects with multiple related fields (forms, config). Never destructure a `reactive` object — you lose reactivity. Use `toRefs(state)` if you need to destructure.