[Vue.js 3.0] API – Basic Reactivity APIs

# Basic Reactivity APIs

This section uses single-file component syntax for code examples

# reactive

Returns a reactive copy of the object.

const obj = reactive({ count: 0 })

The reactive conversion is "deep"—it affects all nested properties. In the ES2015 Proxy(opens new window) based implementation, the returned proxy is not equal to the original object. It is recommended to work exclusively with the reactive proxy and avoid relying on the original object.


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


reactive will unwrap all the deep refs, while maintaining the ref reactivity

const count = ref(1)
const obj = reactive({ count })
// ref will be unwrapped
console.log(obj.count === count.value) // true
// it will update `obj.value`
console.log(count.value) // 2
console.log(obj.count) // 2
// it will also update `count` ref
console.log(obj.count) // 3
console.log(count.value) // 3


When assigning a ref to a reactive property, that ref will be automatically unwrapped.

const count = ref(1)
const obj = reactive({})
obj.count = count
console.log(obj.count) // 1
console.log(obj.count === count.value) // true

# readonly

Takes an object (reactive or plain) or a ref and returns a readonly proxy to the original. A readonly proxy is deep: any nested property accessed will be readonly as well.

const original = reactive({ count: 0 })
const copy = readonly(original)
watchEffect(() => {
// works for reactivity tracking
// mutating original will trigger watchers relying on the copy
// mutating the copy will fail and result in a warning
copy.count++ // warning!

# isProxy

Checks if an object is a proxy created by reactive or readonly.

# isReactive

Checks if an object is a reactive proxy created by reactive.

import { reactive, isReactive } from 'vue'
export default {
setup() {
const state = reactive({
name: 'John'
console.log(isReactive(state)) // -> true

It also returns true if the proxy is created by readonly, but is wrapping another proxy created by reactive.


import { reactive, isReactive, readonly } from 'vue'
export default {
setup() {
const state = reactive({
name: 'John'
// readonly proxy created from plain object
const plain = readonly({
name: 'Mary'
console.log(isReactive(plain)) // -> false
// readonly proxy created from reactive proxy
const stateCopy = readonly(state)
console.log(isReactive(stateCopy)) // -> true

# isReadonly

Checks if an object is a readonly proxy created by readonly.

# toRaw

Returns the raw, original object of a reactive or readonly proxy. This is an escape hatch that can be used to temporarily read without incurring proxy access/tracking overhead or write without triggering changes. It is not recommended to hold a persistent reference to the original object. Use with caution.

const foo = {}
const reactiveFoo = reactive(foo)
console.log(toRaw(reactiveFoo) === foo) // true

# markRaw

Marks an object so that it will never be converted to a proxy. Returns the object itself.

const foo = markRaw({})
console.log(isReactive(reactive(foo))) // false
// also works when nested inside other reactive objects
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false


markRaw and the shallowXXX APIs below allow you to selectively opt-out of the default deep reactive/readonly conversion and embed raw, non-proxied objects in your state graph. They can be used for various reasons:

  • Some values simply should not be made reactive, for example a complex 3rd party class instance, or a Vue component object.

  • Skipping proxy conversion can provide performance improvements when rendering large lists with immutable data sources.

They are considered advanced because the raw opt-out is only at the root level, so if you set a nested, non-marked raw object into a reactive object and then access it again, you get the proxied version back. This can lead to identity hazards - i.e. performing an operation that relies on object identity but using both the raw and the proxied version of the same object:

const foo = markRaw({
nested: {}
const bar = reactive({
// although `foo` is marked as raw, foo.nested is not.
nested: foo.nested
console.log(foo.nested === bar.nested) // false

Identity hazards are in general rare. However, to properly utilize these APIs while safely avoiding identity hazards requires a solid understanding of how the reactivity system works.

# shallowReactive

Creates a reactive proxy that tracks reactivity of its own properties but does not perform deep reactive conversion of nested objects (exposes raw values).

const state = shallowReactive({
foo: 1,
nested: {
bar: 2
// mutating state's own properties is reactive
// ...but does not convert nested objects
isReactive(state.nested) // false
state.nested.bar++ // non-reactive

# shallowReadonly

Creates a proxy that makes its own properties readonly, but does not perform deep readonly conversion of nested objects (exposes raw values).

const state = shallowReadonly({
foo: 1,
nested: {
bar: 2
// mutating state's own properties will fail
// ...but works on nested objects
isReadonly(state.nested) // false
state.nested.bar++ // works
以上是[Vue.js 3.0] API – Basic Reactivity APIs的全部内容。
< <上一篇