Що робить `ref()`?
1. Що робить ref()
Функція ref() створює реактивну обгортку (контейнер) навколо будь-якого значення - примітиву або об'єкта -
і повертає об'єкт зі спеціальною властивістю .value.
import { ref } from 'vue'
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1Ключова ідея:
ref()робить значення реактивним, поміщаючи його в об'єкт вигляду{ value: ... }.
Vue «стежить» за змінами .value,
і автоматично оновлює шаблон або ефекти, що залежать від цього значення.
2. Що робить reactive()
А от reactive() робить об'єкт цілком реактивним (через Proxy).
import { reactive } from 'vue'
const state = reactive({
count: 0,
user: { name: 'Tim' }
})
state.count++ // реактивно
state.user.name = 'Alex' // реактивноVue відстежує всі властивості об'єкта, вкладеність і операції з ними (get, set, delete, push тощо).
3. Головна відмінність
| Характеристика | ref() | reactive() |
|---|---|---|
| Що робить реактивним | Одне значення (зазвичай примітив) | Весь об'єкт |
| Синтаксис | count.value | state.count |
| Працює з примітивами | Так | Ні |
| Працює з об'єктами | Так (обгортає всередині reactive()) | Так |
| Повертає | Об'єкт { value: ... } | Proxy-об'єкт |
| Вкладені властивості | Не реактивні (якщо всередині немає ref/reactive) | Автоматично реактивні |
| Коли використовувати | Просте значення, лічильники, булеві прапорці | Складні структури, об'єкти, масиви |
| У шаблоні Vue | .value не потрібен (автоматичне розпакування) | Звичайний доступ через крапки |
4. Візуально
ref(0)
↓
{ value: 0 } → реактивне значення
reactive({ count: 0 })
↓
Proxy({ count: 0 }) → реактивний об'єкт5. Як ref() працює всередині
ref() реалізований через той самий механізм, що й reactive(), але простіше:
function ref(rawValue) {
let value = reactive(rawValue) // якщо це об'єкт, зробимо його реактивним
const r = {
get value() {
track(r, 'value')
return value
},
set value(newVal) {
if (newVal !== value) {
value = reactive(newVal)
trigger(r, 'value')
}
}
}
return r
}Тобто ref() - це просто об'єкт з геттером і сеттером,
який вміє відстежувати доступ до .value і сповіщати залежні ефекти при зміні.
6. Коли що використовувати
| Сценарій | Що використовувати |
|---|---|
Примітивні значення (число, рядок, boolean) | ref() |
Складні об'єкти (object, array, map) | reactive() |
| Потрібно зберігати одне значення і змінювати його | ref() |
| Потрібно керувати цілим станом | reactive() |
Потрібно деструктурувати (наприклад, при поверненні з setup()) | Краще ref() (щоб не втрачати реактивність) |
7. Підводний камінь: деструктуризація
Якщо ти деструктуруєш reactive-об'єкт, реактивність втрачається:
const state = reactive({ count: 0 })
const { count } = state
count++ // не реактивноТому що count тепер просто число, не Proxy.
А от ref() не втрачає реактивність при деструктуризації,
тому що значення зберігається в .value:
const count = ref(0)
const { value } = count
// але в шаблоні Vue це не потрібно: {{ count }} автоматично бере count.value8. Можна поєднувати ref і reactive
Vue автоматично розпаковує ref всередині reactive:
const count = ref(0)
const state = reactive({ count })
console.log(state.count) // не потрібно .value
state.count++ // працює і оновлює count.value тежТобто reactive() «розуміє» ref() і робить доступ до нього зручним.
9. У шаблоні (template)
-
У шаблоні
.valueне потрібно писати:javascript<template> <p>{{ count }}</p> <!-- автоматично бере count.value --> </template>
Vue робить автоматичне «розпакування» (unwrapping) ref всередині шаблонів.
10. Підсумок
| Критерій | ref() | reactive() |
|---|---|---|
| Для чого | Примітивні значення | Об'єкти і масиви |
| Тип результату | { value: ... } | Proxy |
| Вкладені об'єкти | Не реактивні (потрібно вручну) | Глибоко реактивні |
| Зручний для | Простих станів, полів, прапорців | Комплексних структур даних |
| Авто-unwrap у шаблонах | Так | Не потрібен |
| Втрата реактивності при деструктуризації | Ні | Так |
Коротко:
ref()- робить реактивним одне значення (зазвичай примітив).reactive()- робить реактивним весь об'єкт (і весь його вміст).Разом вони дають повний контроль над станом:
ref()- точковий,reactive()- структурний.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.