Vue 3 Reactivity Transform w 2026: $ref, $computed i Pytania Rekrutacyjne
Kompleksowy przewodnik po Vue 3 Reactivity Transform w 2026. Poznaj makra $ref, $computed, $shallowRef oraz najczęstsze pytania na rozmowach kwalifikacyjnych dla programistów Vue.

Vue 3 Reactivity Transform stanowi przełomową zmianę w sposobie pracy z reaktywnością we frameworku. Ta funkcjonalność, wprowadzona w celu uproszczenia składni Composition API, przeszła szereg iteracji zanim osiągnęła obecną formę w 2026 roku. Zrozumienie jej działania, zalet i ograniczeń jest kluczowe dla każdego programisty Vue dążącego do opanowania zaawansowanych koncepcji frameworka.
Reactivity Transform został oficjalnie ustabilizowany w Vue 3.5. Makra $ref, $computed i $shallowRef są dostępne poprzez dedykowany plugin Vite, oddzielony od rdzenia Vue.
Problem Rozwiązywany przez Reactivity Transform
Standardowe Composition API w Vue 3 wymaga użycia .value do uzyskania dostępu i modyfikacji wartości reaktywnych tworzonych za pomocą ref(). Ta składnia, choć jawna, wprowadza dodatkowe obciążenie poznawcze i może generować subtelne błędy, gdy programista zapomni użyć .value.
import { ref, computed } from 'vue'
// Standardowa składnia Composition API
const count = ref(0)
const doubled = computed(() => count.value * 2)
function increment() {
count.value++ // .value wymagane
}
console.log(doubled.value) // .value również wymaganeReactivity Transform eliminuje tę konieczność poprzez automatyczną transformację kodu w czasie kompilacji. Zmienne zadeklarowane za pomocą makr reaktywności zachowują się jak zwykłe zmienne JavaScript, jednocześnie zachowując swoją reaktywną naturę.
Makra $ref i $computed
Makra $ref i $computed stanowią rdzeń Reactivity Transform. Umożliwiają deklarowanie wartości reaktywnych bez konieczności ręcznego manipulowania .value.
<script setup>
// Z Reactivity Transform
let count = $ref(0)
const doubled = $computed(() => count * 2)
function increment() {
count++ // Bez .value
}
console.log(doubled) // Bezpośredni dostęp
</script>
<template>
<button @click="increment">{{ count }} (podwojone: {{ doubled }})</button>
</template>Kompilator Vue przekształca ten kod w standardową składnię z ref() i .value przed wykonaniem. Ta transformacja jest przezroczysta dla programisty i nie zmienia zachowania kodu.
Mechanizm Transformacji
Kompilator analizuje kod i stosuje następujące przekształcenia:
$ref(value)staje sięref(value)- Dostępy do zmiennej stają się
variable.value - Przypisania stają się
variable.value = newValue
// Kod źródłowy z Reactivity Transform
let message = $ref('Witaj')
message = 'Do widzenia'
console.log(message)
// Kod przekształcony przez kompilator
const message = ref('Witaj')
message.value = 'Do widzenia'
console.log(message.value)Konfiguracja Reactivity Transform z Vite
Aktywacja Reactivity Transform wymaga specyficznej konfiguracji w projekcie Vue. W 2026 roku ta funkcjonalność jest dostarczana poprzez plugin @vue/reactivity-transform.
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { reactivityTransform } from '@vue/reactivity-transform'
export default defineConfig({
plugins: [
vue(),
reactivityTransform()
]
})Dla projektów wykorzystujących TypeScript, dodatkowa konfiguracja zapewnia rozpoznawanie typów makr.
{
"compilerOptions": {
"types": ["@vue/reactivity-transform"]
}
}$shallowRef i Inne Zaawansowane Makra
Oprócz $ref i $computed, Reactivity Transform zawiera inne makra dla specyficznych przypadków użycia.
<script setup>
import { watchEffect } from 'vue'
// $shallowRef dla dużych obiektów
let largeObject = $shallowRef({ data: [], metadata: {} })
// Tylko referencja jest reaktywna, nie wewnętrzne właściwości
largeObject = { data: [1, 2, 3], metadata: { updated: true } }
// $toRef do konwersji prop na ref
const props = defineProps<{ initialValue: number }>()
let value = $(props.initialValue) // Odpowiednik toRef(props, 'initialValue')
watchEffect(() => {
console.log('Wartość zmieniona:', value)
})
</script>Makro $() do Reaktywnej Destrukturyzacji
Makro $() umożliwia destrukturyzację obiektów reaktywnych z zachowaniem reaktywności każdej wyodrębnionej właściwości.
<script setup>
import { reactive } from 'vue'
const state = reactive({
firstName: 'Jan',
lastName: 'Kowalski',
age: 30
})
// Destrukturyzacja z zachowaniem reaktywności
const { firstName, lastName } = $(state)
// firstName i lastName pozostają reaktywne
function updateName() {
firstName = 'Piotr' // Modyfikuje state.firstName
}
</script>Integracja z Composables
Reactivity Transform naturalnie integruje się z composables, upraszczając ich używanie i tworzenie.
export function useCounter(initial = 0) {
let count = $ref(initial)
const doubled = $computed(() => count * 2)
const isEven = $computed(() => count % 2 === 0)
function increment() {
count++
}
function decrement() {
count--
}
function reset() {
count = initial
}
// $$() konwertuje refs na standardowe obiekty ref przy zwracaniu
return $$({ count, doubled, isEven, increment, decrement, reset })
}Użycie composable staje się bardziej intuicyjne.
<script setup>
import { useCounter } from '@/composables/useCounter'
// Destrukturyzacja z $() zachowuje reaktywność
const { count, doubled, increment, reset } = $(useCounter(10))
</script>
<template>
<div>
<p>Licznik: {{ count }} (Podwojone: {{ doubled }})</p>
<button @click="increment">+</button>
<button @click="reset">Reset</button>
</div>
</template>Obsługa Props z Reactivity Transform
Konwersja props na lokalnie modyfikowalne refs reaktywne to częsty przypadek użycia Reactivity Transform.
<script setup>
const props = defineProps<{
modelValue: string
disabled?: boolean
}>()
const emit = defineEmits<{
'update:modelValue': [value: string]
}>()
// Tworzenie lokalnego ref powiązanego z prop
let localValue = $ref(props.modelValue)
// Dwukierunkowa synchronizacja
watch(
() => props.modelValue,
(newVal) => { localValue = newVal }
)
watch(
() => localValue,
(newVal) => { emit('update:modelValue', newVal) }
)
</script>
<template>
<input v-model="localValue" :disabled="disabled" />
</template>Pytania Rekrutacyjne o Reactivity Transform
Rozmowy techniczne dotyczące Vue 3 często zawierają pytania o Reactivity Transform. Poniższe pytania reprezentują najczęściej poruszane tematy.
Pytanie 1: Jaka jest różnica między $ref a ref?
Oczekiwana odpowiedź: $ref jest makrem kompilacji generującym kod używający ref() z automatycznym dostępem do .value. Różnica jest czysto składniowa na poziomie kodu źródłowego. W czasie wykonania oba produkują ten sam wynik. $ref poprawia ergonomię programisty eliminując konieczność ręcznego pisania .value.
Pytanie 2: Dlaczego używać $$() przy zwracaniu wartości z composable?
Oczekiwana odpowiedź: Makro $$() konwertuje zmienne przekształcone przez Reactivity Transform na standardowe obiekty ref. Bez tej konwersji zwracane wartości byłyby prymitywami tracącymi reaktywność. $$() zapewnia, że konsument composable otrzymuje reaktywne refs, które może używać z $() do destrukturyzacji.
Pytanie 3: Czy Reactivity Transform działa z Options API?
Oczekiwana odpowiedź: Nie. Reactivity Transform jest zaprojektowany wyłącznie dla Composition API z <script setup>. Opiera się na statycznej analizie kodu podczas kompilacji, co nie jest kompatybilne z dynamiczną strukturą Options API.
Pytanie 4: Jak debugować kod używający Reactivity Transform?
Oczekiwana odpowiedź: Kod źródłowy widoczny w narzędziach deweloperskich to kod przekształcony, nie oryginalny. Dla efektywnego debugowania zaleca się używanie source maps i zrozumienie stosowanej transformacji. Vue DevTools poprawnie wyświetla wartości reaktywne niezależnie od użytej składni.
// Aby zobaczyć bazowy ref podczas debugowania
let count = $ref(0)
console.log($$(count)) // Wyświetla pełny obiekt refPytanie 5: Jakie są typowe pułapki Reactivity Transform?
Oczekiwana odpowiedź: Główne pułapki obejmują:
- Zapomnienie
$$()przy zwracaniu wartości z funkcji - Mieszanie standardowej składni i składni przekształconej w tym samym pliku
- Założenie, że wszystkie operacje JavaScript działają identycznie (niektóre złożone przypisania mogą wymagać szczególnej uwagi)
- Brak poprawnej konfiguracji TypeScript do rozpoznawania typów makr
Porównanie ze Standardową Składnią
Bezpośrednie porównanie ilustruje różnice między oboma podejściami.
<!-- Bez Reactivity Transform -->
<script setup>
import { ref, computed, watch } from 'vue'
const items = ref<string[]>([])
const filter = ref('')
const filteredItems = computed(() =>
items.value.filter(item => item.includes(filter.value))
)
function addItem(item: string) {
items.value.push(item)
}
watch(filter, (newFilter) => {
console.log('Filtr zmieniony:', newFilter)
})
</script><!-- Z Reactivity Transform -->
<script setup>
import { watch } from 'vue'
let items = $ref<string[]>([])
let filter = $ref('')
const filteredItems = $computed(() =>
items.filter(item => item.includes(filter))
)
function addItem(item: string) {
items.push(item)
}
watch($$(filter), (newFilter) => {
console.log('Filtr zmieniony:', newFilter)
})
</script>Gotowy na rozmowy o Vue.js / Nuxt.js?
Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.
Dobre Praktyki i Rekomendacje
Adopcja Reactivity Transform w istniejącym projekcie wymaga metodycznego podejścia dla zachowania spójności kodu.
Spójność w projekcie: Wybór jednego podejścia (standardowego lub przekształconego) i jego konsekwentne stosowanie. Mieszanie obu składni komplikuje czytanie i utrzymanie kodu.
Jawna dokumentacja: Dokumentowanie użycia Reactivity Transform w README projektu i przewodnikach kontrybutorów. Nowi programiści muszą rozumieć stosowaną składnię.
Testy jednostkowe: Testy działają identycznie niezależnie od użytej składni, ponieważ kod jest przekształcany przed wykonaniem. Żadne modyfikacje istniejących testów nie są potrzebne podczas migracji.
Stopniowa migracja: Dla istniejących projektów, migracja plik po pliku zamiast konwertowania wszystkiego jednocześnie. To podejście redukuje ryzyko wprowadzenia błędów.
Reactivity Transform reprezentuje znaczącą poprawę ergonomii programowania w Vue 3. Jego opanowanie demonstruje głębokie zrozumienie systemu reaktywności Vue i stanowi atut podczas rozmów technicznych na stanowiska starszego programisty Vue.
Znajdziesz błąd w Vue.js / Nuxt.js?
Prawdziwy fragment kodu, ukryty błąd, jedna próba dziennie. Bez konta, żeby spróbować.

Autor:
Anthony Fillion-MailletZałożyciel SharpSkill
Programista fullstack od ponad 10 lat. Prowadzi SharpSkill i odpowiada za wszystko, co się tu ukazuje.
Zaktualizowano 9 września 2026
Udostępnij
Powiązane artykuły

Vue 3 Script Setup i defineModel w 2026: Nowoczesna Składnia i Pytania Rekrutacyjne
Kompleksowy przewodnik po składni script setup w Vue 3 oraz makrze defineModel. Omówienie reactive props destructure, typowania TypeScript oraz pytań rekrutacyjnych.

Nuxt 4 SEO i Meta Tagi w 2026: useHead, useSeoMeta i Pytania Rekrutacyjne
Kompleksowy przewodnik po SEO w Nuxt 4 z kompozytorami useHead i useSeoMeta. Typowane meta tagi, optymalizacja wydajności, kompatybilność z crawlerami AI oraz pytania na rozmowach technicznych.

Vue 3 Teleport i Suspense: Zaawansowane Wzorce i Pytania Rekrutacyjne 2026
Kompleksowy przewodnik po Vue 3 Teleport i Suspense - zaawansowane wzorce renderowania, obsługa błędów oraz najczęstsze pytania na rozmowach kwalifikacyjnych dla seniorów Vue.