Wat is Reactivity?
Reactivity is data die kan veranderen in je component. Denk aan: een teller, een toggle, input waardes, of een lijst die groeit.
Waarom is reactivity nodig?
In Vue refresht je browser niet zoals bij gewone HTML. Als je een normale variabele verandert (bijvoorbeeld let count = 5), dan zie je dat niet op je scherm!
Vue's reactivity-systeem zorgt ervoor dat de UI automatisch updatet wanneer reactive data verandert. Zonder reactivity zie je niks gebeuren.
Wanneer gebruik je reactivity?
- Teller die omhoog/omlaag gaat
- Modal die open/dicht gaat
- Input waardes onthouden
- Lijst waar items aan toegevoegd worden
- Alles wat op je scherm moet veranderen!
Let op: Een normale variabele werkt NIET reactief in Vue:
let count = 0
count = count + 1 // Verandert wel, maar de UI updatet niet!
Je hebt ref() of reactive() nodig om Vue te laten weten: "Hey, herrender de UI!"
ref() — de eerste keus
Om reactivity te gebruiken, importeer je ref uit Vue:
import { ref } from 'vue'
Basis Syntax
const state = ref(beginWaarde)
state— Een reactive containerstate.value— De huidige waarde (in JavaScript){{ state }}— In de template hoef je.valueNIET te schrijvenbeginWaarde— Startwaarde (bijv.0,"",[], een object)
Eerste Voorbeeld: Counter
<script setup>
import { ref } from 'vue'
const count = ref(0)
const increment = () => {
count.value++ // ⚠️ .value in JS
}
</script>
<template>
<p>Count: {{ count }}</p> <!-- ✅ geen .value in template -->
<button @click="increment">+1</button>
</template>
Wat gebeurt er?
countstart op 0- Bij klik wordt
count.value++uitgevoerd - Vue's reactivity-systeem detecteert de wijziging
- De UI updatet automatisch — alleen het stukje dat veranderd is
De grote valkuil voor beginners: in JavaScript moet je .value gebruiken, in de template NIET.
// JavaScript
count.value++ // ✅
count++ // ❌ werkt niet
// Template
{{ count }} // ✅
{{ count.value }} // ❌ werkt wel, maar onnodig
Zie de cycle in actie
Wat betekent "Vue updatet de UI automatisch"? Hieronder zie je het visueel. Er staat een Profile component met twee soorten state: een naam en een status. Verander één van beide — typen, klikken, maakt niet uit — en kijk hoe het diagram links de cycle doorloopt.
De Cycle
ref.value is geüpdatetref gebruikenHet Profile Component
Het verschil met React: in React draait bij elke state-wijziging de hele component-functie opnieuw. In Vue draait je <script setup> maar één keer bij het mounten — daarna update Vue alleen de specifieke template-stukjes die de geüpdatete ref gebruiken. Dat is wat Vue's reactivity-systeem zo efficiënt maakt.
Objecten & Arrays met ref()
Het mooie van ref() is dat het voor alles werkt — niet alleen voor primitives. Een object of array? Gewoon in ref() stoppen.
Object in ref
<script setup>
import { ref } from 'vue'
const user = ref({
name: 'Anna',
age: 25,
hobbies: ['lezen', 'gamen']
})
const birthday = () => {
user.value.age++ // ✅ property muteren
}
const rename = () => {
user.value.name = 'Bram' // ✅ property muteren
}
const replaceUser = () => {
user.value = { name: 'Chloé', age: 30, hobbies: [] } // ✅ hele object vervangen mag
}
</script>
<template>
<p>{{ user.name }} is {{ user.age }}</p>
<button @click="birthday">Verjaardag!</button>
</template>
Hoe onthoud je het?
- In JS gebruik je
.valueom bij het object te komen - Daarna werk je gewoon met properties:
user.value.name = 'Bram' - In templates schrijf je
{{ user.name }}— geen.value
Array in ref
<script setup>
import { ref } from 'vue'
const todos = ref(['Boodschappen', 'Vue leren'])
const addTodo = (text) => {
todos.value.push(text) // ✅ muteren mag
}
const removeFirst = () => {
todos.value.shift() // ✅
}
const clearAll = () => {
todos.value = [] // ✅ hele array vervangen mag
}
</script>
Goed nieuws: Anders dan in React mag je arrays en objecten in Vue gewoon muteren met push, splice, etc. Vue's reactivity-systeem detecteert het. Je hoeft niet "een nieuwe array te maken" zoals [...items, nieuw] — al mag dat ook.
State Updaten — alle manieren
Primitives
const count = ref(0)
// Direct toewijzen
count.value = 5
// Berekenen
count.value = count.value + 1
count.value++
Objecten
const user = ref({ name: 'Anna' })
// Property aanpassen
user.value.name = 'Bram'
// Hele object vervangen
user.value = { name: 'Chloé' }
Arrays
const items = ref([])
// Toevoegen
items.value.push('nieuw')
// Verwijderen
items.value = items.value.filter(i => i !== 'oud')
// Vervangen
items.value = ['a', 'b', 'c']
Praktische Voorbeelden
Toggle (aan/uit)
<script setup>
import { ref } from 'vue'
const isOn = ref(false)
</script>
<template>
<p>Status: {{ isOn ? 'Aan' : 'Uit' }}</p>
<button @click="isOn = !isOn">Toggle</button>
</template>
Input Waarde (met v-model)
<script setup>
import { ref } from 'vue'
const name = ref('')
</script>
<template>
<input v-model="name" placeholder="Typ je naam" />
<p>Hallo, {{ name }}!</p>
</template>
Met v-model heb je geen event handler nodig — Vue regelt two-way binding voor je. Dit scheelt veel code vergeleken met React.
Lijst met Items
<script setup>
import { ref } from 'vue'
const todos = ref([])
const input = ref('')
const addTodo = () => {
if (input.value.trim()) {
todos.value.push(input.value)
input.value = ''
}
}
</script>
<template>
<input v-model="input" />
<button @click="addTodo">Add</button>
<ul>
<li v-for="(todo, i) in todos" :key="i">{{ todo }}</li>
</ul>
</template>
reactive() — bestaat ook, maar skip dit
In tutorials kom je soms reactive() tegen. Dat is een tweede manier om reactive state te maken, speciaal voor objecten. Het ziet er zo uit:
import { reactive } from 'vue'
const user = reactive({ name: 'Anna', age: 25 })
user.age++ // geen .value nodig
Waarom je het beter NIET gebruikt:
- Destructuring breekt reactivity:
const { age } = user→ageis geen reactive meer - Je mag het object niet vervangen:
user = { ... }verbreekt de reactivity - Werkt niet voor primitives (alleen objecten/arrays)
- De rest van het Vue-ecosysteem (composables, VueUse) gebruikt refs — mixen is verwarrend
Conclusie: reactive() is niet deprecated, maar de community is grotendeels overgestapt op "altijd ref()". Je hoeft het alleen te herkennen in oudere code — zelf gebruiken hoeft niet.
Belangrijke Regels
- In JS gebruik je
.value, in templates niet ref()werkt voor alles — primitives, objecten, arrays- Arrays en objecten muteren mag (push, splice) — Vue detecteert het
- Hele objecten/arrays vervangen mag ook (
user.value = nieuwObject) - Reactivity werkt alleen op refs — niet op losse variabelen
Veelgemaakte Fouten
Fout — .value vergeten in JS:
const count = ref(0)
count++ // ❌ werkt niet (count is een ref-object)
console.log(count) // ❌ logt de ref, niet 0
Goed:
count.value++ // ✅
console.log(count.value) // ✅ logt 0
Fout — .value vergeten bij property:
const user = ref({ name: 'Anna' })
user.name = 'Bram' // ❌ user is een ref, niet het object
console.log(user.name) // ❌ undefined
Goed:
user.value.name = 'Bram' // ✅
console.log(user.value.name) // ✅ 'Bram'
Fout — gewone variabele i.p.v. ref:
<script setup>
let count = 0 // ❌ niet reactive
</script>
<template>
<p>{{ count }}</p>
<button @click="count++">+1</button> <!-- UI updatet niet -->
</template>
Goed:
<script setup>
import { ref } from 'vue'
const count = ref(0) // ✅ reactive
</script>