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 w 2026: $ref, $computed i Pytania Rekrutacyjne

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.

Status Reactivity Transform w 2026

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.

typescript
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ż wymagane

Reactivity 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.

vue
<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:

  1. $ref(value) staje się ref(value)
  2. Dostępy do zmiennej stają się variable.value
  3. Przypisania stają się variable.value = newValue
typescript
// 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.

vite.config.tstypescript
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.

tsconfig.jsonjson
{
  "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.

vue
<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.

vue
<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.

composables/useCounter.tstypescript
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.

vue
<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.

vue
<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.

typescript
// Aby zobaczyć bazowy ref podczas debugowania
let count = $ref(0)
console.log($$(count)) // Wyświetla pełny obiekt ref

Pytanie 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.

vue
<!-- 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>
vue
<!-- 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.

Wyzwanie dnia

Znajdziesz błąd w Vue.js / Nuxt.js?

Prawdziwy fragment kodu, ukryty błąd, jedna próba dziennie. Bez konta, żeby spróbować.

Anthony Fillion-Maillet

Autor:

Anthony Fillion-Maillet

Zał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