This is the third day of my participation in the August More Text Challenge

What is reactive

Responsiveness is a programming paradigm that allows us to adapt to change in a declarative way. When a value is evaluated by attaching to another value, if the previous value changes, the attached value changes at the same time. For a typical example, see Excel functions. When cell A3=SUM(A1:A2), when A1 or A2 changes at this time, A3 will immediately respond to update.

Responsiveness is the core API of Vue3. There is also a separate package for this responsive API that can be used independently even without Vue3: @vue/ reActivity

Responsive API- Extended approach

Vue3 has two core reactive methods: REF, which is a response to a single value, and Reactive, which is a deep response to an object.

This chapter introduces extensions around the core methods of reactive apis that were introduced in the previous section.

There are six extension methods for reactive:

  • readonly()
  • isReadonly()
  • toRaw()
  • markRaw()
  • shallowReactive()
  • shallowReadonly()

readonlyCreating a read-only object

A read-only object is, as its name implies, an object that cannot be changed (an object whose property value cannot be changed). A read-only proxy that takes an object (reactive or pure) or ref and returns the original object. A read-only proxy is deep: any nested property accessed is also read-only.

const original = reactive({ count: 0 })

const copy = readonly(original)

watchEffect(() = > {
  // For responsiveness tracing
  console.log(copy.count)
})

// Changing original triggers listeners that depend on replicas
original.count++

// Changing copies will fail and cause a warning
copy.count++ / / warning!
Copy the code

Like Reactive, if any property uses ref, it is automatically unpacked when accessed by proxy:

const raw = {
  count: ref(123)}const copy = readonly(raw)

console.log(raw.count.value) / / 123
console.log(copy.count) / / 123
Copy the code

In the Vue Options API, props is a read-only object that only allows passing down data.

isReadonlyCheck whether it is a read-only object

Check whether the object is a read-only proxy created by ReadOnly.

const raw = {
  name: "Jerry"
}

const reactiveRaw = reactive(raw)
const readonlyRaw = readonly(raw)

console.log(isReadonly(raw)) // false
console.log(isReadonly(reactiveRaw)) // false
console.log(isReadonly(readonlyRaw)) // true
Copy the code

toRawReturn the original object

Returns the original object of the Reactive or Readonly agent. This is an “escape pod” that can be used to temporarily read data without the overhead of proxy access/trace, or to write data without triggering changes. It is not recommended to preserve persistent references to the original object. Use with caution.

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

console.log(toRaw(reactiveFoo) === foo) // true
Copy the code

This method is rarely used unless it is possible to preserve a snapshot of the state under the current reactive.

markRawDisallow the creation of reactive types

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

// Can also be used when nested within other reactive objects
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false
Copy the code

emmmm… Currently only mark objects do not have methods to untag objects. For example, if you want to be compatible with another framework under vUE, but that framework should not be reactive, you can do so. Example: Map API. Therefore, be careful to mark specific objects for specific purposes in the current usage scenario.

shallowReactive

Create a reactive proxy that tracks the responsiveness of its own property, but does not perform deep reactive transformations of nested objects (exposing raw values)

const state = shallowReactive({
  foo: 1.nested: {
    bar: 2}})// Changing the nature of state itself is reactive
state.foo++
/ /... But nested objects are not converted
isReactive(state.nested) // false
state.nested.bar++ // non-responsive
Copy the code

Unlike Reactive, any property that uses ref is not automatically unpacked by the agent.

shallowReadonly

Create a proxy that makes its own property read-only but does not perform deep read-only conversions of nested objects (exposing raw values).

const state = shallowReadonly({
  foo: 1.nested: {
    bar: 2}})// Changing the property of state itself will fail
state.foo++
/ /... But it applies to nested objects
isReadonly(state.nested) // false
state.nested.bar++ / / for
Copy the code

The official tomarkRaw,shallowXXXImportant note of

The markRaw and shallowXXX methods allow you to selectively exit the default deep responsive/read-only transformation mode and embed raw, unproxied objects into the state graph. They can be used flexibly according to the situation:

  • Some values should not be reactive, such as complex third-party class instances or Vue component objects.
  • Skipping proxy transformations can improve performance when rendering large lists with immutable data sources.

These examples are advanced because the original opt-out is only at the root level, so if you add a nested, unmarked original object to a reactive object and then access that reactive object again, you get the proxied version of the original object. This can lead to an identity risk — that is, performing an operation that depends on the object itself but uses both the original and the proxied version of the same object:

const foo = markRaw({
  nested: {}})const bar = reactive({
  // Although 'foo' is marked original, foo.nested is not.
  nested: foo.nested
})

console.log(foo.nested === bar.nested) // false
Copy the code

Identity risk is usually rare. However, in order to use these apis correctly while safely avoiding the risk of identity, a good understanding of how responsive systems work is required.

The literature

  • Vue3 responsive base API