# Основное API реактивности

В этом разделе в примерах кода используется синтаксис однофайловых компонентов

# reactive

Возвращает реактивную копию объекта.

const obj = reactive({ count: 0 })
1

Реактивное преобразование «глубокое» — оно будет затрагивать все вложенные свойства. В реализации, основанной на ES2015 Proxy (opens new window), возвращаемый прокси НЕ БУДЕТ РАВЕН оригинальному объекту. Рекомендуется работать исключительно с реактивным прокси и не полагаться на оригинальный объект.

Типизация:

function reactive<T extends object>(target: T): UnwrapNestedRefs<T>
1

Примечание

reactive разворачивает вложенные ref-ссылки и при этом сохраняет их реактивность

const count = ref(1)
const obj = reactive({ count })

// ссылка будет развёрнута
console.log(obj.count === count.value) // true

// изменения будут обновлять `obj.count`
count.value++
console.log(count.value) // 2
console.log(obj.count) // 2

// изменения будут влиять и на ссылку `count`
obj.count++
console.log(obj.count) // 3
console.log(count.value) // 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Важно

При присвоении ref-ссылки в свойство reactive она разворачивается автоматически.

const count = ref(1)
const obj = reactive({})

obj.count = count

console.log(obj.count) // 1
console.log(obj.count === count.value) // true
1
2
3
4
5
6
7

# readonly

Принимает объект (реактивный или обычный) или ref-ссылку и возвращает доступную только для чтения прокси к оригиналу. Прокси только для чтения «глубокие»: любое вложенное свойство также доступно только для чтения.

const original = reactive({ count: 0 })

const copy = readonly(original)

watchEffect(() => {
  // работает для отслеживания реактивности
  console.log(copy.count)
})

// изменение оригинала вызывает методы-наблюдатели, которые отслеживают копию
original.count++

// изменение копии не сработает и приведёт к предупреждению
copy.count++ // ПРЕДУПРЕЖДЕНИЕ, потому что только для чтения!
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Как и в случае с reactive, если какое-либо свойство использует ref, то оно будет автоматически разворачиваться при доступе через прокси:

const raw = {
  count: ref(123)
}

const copy = readonly(raw)

console.log(raw.count.value) // 123
console.log(copy.count) // 123
1
2
3
4
5
6
7
8

# isProxy

Проверяет, является ли объект прокси, созданной с помощью reactive или readonly.

# isReactive

Проверяет, является ли объект реактивной прокси, созданной с помощью reactive.

import { reactive, isReactive } from 'vue'
export default {
  setup() {
    const state = reactive({
      name: 'John'
    })

    console.log(isReactive(state)) // -> true
  }
}
1
2
3
4
5
6
7
8
9
10

Возвращает true, если прокси создавалась с помощью readonly, но оборачивается другой прокси, созданной с помощью reactive.









 
 
 
 
 
 
 
 
 



import { reactive, isReactive, readonly } from 'vue'

export default {
  setup() {
    const state = reactive({
      name: 'John'
    })

    // прокси только для чтения, созданная из обычного объекта
    const plain = readonly({
      name: 'Mary'
    })
    console.log(isReactive(plain)) // -> false

    // прокси только для чтения, созданная из реактивной прокси
    const stateCopy = readonly(state)
    console.log(isReactive(stateCopy)) // -> true
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# isReadonly

Проверяет, является ли объект прокси только для чтения, созданной с помощью readonly.

# toRaw

Возвращает исходный оригинальный объект из reactive или readonly прокси. Применяется в крайнем случае, когда нужно только чтение без доступа/отслеживания или запись без инициирования изменений. Не рекомендуется хранить постоянную ссылку на оригинальный объект. Используйте с осторожностью.

const foo = {}
const reactiveFoo = reactive(foo)

console.log(toRaw(reactiveFoo) === foo) // true
1
2
3
4

# markRaw

Отмечает объект, чтобы он никогда не преобразовывался в прокси. Возвращает сам объект.

const foo = markRaw({})
console.log(isReactive(reactive(foo))) // false

// работает даже если вложен в другие реактивные объекты
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false
1
2
3
4
5
6

ВНИМАНИЕ

API markRaw и shallowXXX (см.ниже) позволяют выборочно отказаться от глубокого реактивного/только для чтения преобразования по умолчанию и встраивать исходные, не-проксированные объекты в диаграмму состояния. Причины, по которым это может использоваться:

  • Некоторые значение не должны быть реактивными. Например, сторонний комплексный экземпляр класса или объект компонента Vue.

  • Пропуск преобразования в прокси может улучшить производительность при отрисовке больших списков с иммутабельными (неизменяемыми) данными.

Пропуск преобразования — продвинутая техника, потому что опциональное отключение доступно только на корневом уровне. Если установить вложенный неотмеченный исходный объект в реактивный объект и получить к нему доступ, то вернётся его проксированная версия. Это может привести к опасности идентификации, то есть к выполнению операции, которая основывается на идентификации объекта, но использует как исходную, так и проксированную версию одного и того же объекта:

const foo = markRaw({
  nested: {}
})

const bar = reactive({
  // хотя `foo` отмечен как raw, foo.nested не будет таким.
  nested: foo.nested
})

console.log(foo.nested === bar.nested) // false
1
2
3
4
5
6
7
8
9
10

С опасностью идентификации сталкиваются редко. Однако, чтобы безопасно использовать API markRaw и shallowXXX, нужно твёрдо понимать, как работает система реактивности.

# shallowReactive

Создаёт реактивный прокси, который отслеживает реактивность собственных свойств. Не выполняет глубокое реактивное преобразование вложенных объектов, предоставляя доступ к сырым значениям.

const state = shallowReactive({
  foo: 1,
  nested: {
    bar: 2
  }
})

// изменение состояния собственных свойств реактивно
state.foo++
// ...но вложенные объекты не преобразуются
isReactive(state.nested) // false
state.nested.bar++ // НЕ-РЕАКТИВНО
1
2
3
4
5
6
7
8
9
10
11
12

В отличие от reactive, любое свойство, использующее ref, не будет автоматически разворачиваться прокси.

# shallowReadonly

Создаёт прокси, который делает собственные свойства доступными только для чтения. При этом вложенные объекты не преобразуются, предоставляя доступ к сырым значениям.

const state = shallowReadonly({
  foo: 1,
  nested: {
    bar: 2
  }
})

// изменение состояния собственных свойств не сработает
state.foo++
// ...но сработает на вложенных объектах
isReadonly(state.nested) // false
state.nested.bar++ // сработает
1
2
3
4
5
6
7
8
9
10
11
12

В отличие от readonly, любое свойство, которое использует ref, не будет автоматически разворачиваться с помощью прокси.