[vue3 getting started to the ground] - responsive api usage and application scenarios

ref

Create a responsive data, which is generally used to create simple types of responsive objects, such as String and Number types

const name = ref('tom')
Copy code

As you can see, the ref method wraps the string in a layer and returns an object of type RefImpl, which is translated into a reference implementation. An enumerable attribute value is set on the object, so name.value is used to read the value.

As mentioned above, ref is usually used to define a simple type. Can you define an object or array?

const obj = ref({
  age: 12,
  sex: 'man',
})
Copy code

The console can see that for complex objects, the value is an object intercepted and processed by the proxy, but the attributes age and sex inside are not RefImpl objects. The proxy objects are also mounted on the value, so you can read the attributes through obj.value.age. These attributes are also responsive. When changing, you can trigger the update of the view

reactive

Through the use case of ref above, ref can be used to define complex reference types, such as array and object, or simple value types, such as string and number. However, when defining objects, it is usually implemented with reactive

const person = reactive({
  height: 180,
})
Copy code

You can see that the returned person is a proxy object. You can use person.height

Can reactive be used to define common types?

const id = reactive('id Yes 1')
Copy code

You can see that * * reactive can only be used to define objects**

Differences and relations between ref and reactive

Generally speaking, ref is used to define simple strings or values, while reactive is used to define object arrays, etc

When ref defines an object, value returns a proxy, and when reactive defines an object, it also returns a proxy. There are some connections

When ref is used to define data, a layer of judgment will be made on the data types inside. When complex reference types are encountered, reactive will still be used for processing

class RefImpl {
    constructor(value, _shallow) {
        this._shallow = _shallow;
        this.dep = undefined;
        this.__v_isRef = true;
        this._rawValue = _shallow ? value : toRaw(value);
        this._value = _shallow ? value : toReactive(value);
    }
    ////......
}
Copy code
const toReactive = (value) => isObject(value) ? reactive(value) : value;// Judge whether the parameter is an object. The object calls reactive to create it. Otherwise, the original value is returned
 Copy code

shallowRef and shallowReactive

Both ref and reactive are in-depth monitoring of data. No matter simple types or complex objects, view updates are triggered whenever changes occur. For deep-seated objects, if only a few attributes are easy to change, it is undoubtedly a waste of performance to still monitor the overall attributes of this huge object, In this case, shallowRef or shallowReactive can be used to realize shallow listening

shallowRef

Only monitor the change of the value of the. Value attribute. The update will not be triggered when a property inside the object is changed. The update will be triggered only when the value is changed to re assign the value to the object

const foo = shallowRef({
  c: 1,
})
const change = () => {
  foo.value.c = 2 // The view is not updated
  foo.value={a:1} // View update
}
Copy code

shallowReactive

Only listen to the first layer properties of objects, and do not respond to nested objects

const state = shallowReactive({
  foo: 1,
  nested: {
    bar: 2
  }
})
const change = () => {
  state.foo = 2 // View update
  state.nested={count:2}// View update
  state.nested.bar =3 // The view is not updated
}

Copy code

triggerRef

It is used to manually force the update of the side effects related to the shallowRef and update the view. It can be seen from the above summary that the shallowRef only listens to the value attribute and does not trigger the update when the internally nested objects change. The function of triggerRef is to forcibly trigger the refresh of shallowRef in some cases. For example, in some cases, an object is nested with hundreds of layers of data, but the data of one layer needs to be changed, and the others do not move. All become responsive, wasting performance, and non responsive can not update the view. In this case, you need to change this layer of data and then use triggerRef to update it

const shallow = shallowRef({
  greet: 'Hello, world'
})
shallow.value.greet = 'Hello, universe' // The view does not update
triggerRef(shallow) // Manually update the relevant side effects and update the view
 Copy code

readonly and shallowReadonly

Make object read-only

readonly

Receive a normal object or a responsive object processed by reactive and ref to make it a read-only object, and no data in it can be changed

const original = reactive({ count: 0 })
const copy = readonly(original)

original.count++ // You can still change the responsive object
copy.count++ // If you change it after being wrapped by readonly, you will be warned
 Copy code

shallowReadonly

The first level property of the object is set to read-only, and the nested genera can still be changed

const state = shallowReadonly({
  foo: 1,
  nested: {
    bar: 2
  }
})
state.foo++ //Warning, cannot be changed

state.nested.bar++ // Nested properties can still be changed
 Copy code

toRaw and markRaw

Turn responsive objects back into normal objects

toRaw

Return the proxy object that has been proxied by reactive or readonly, or ref the value when defining the object

const count = ref({
  a: 1,
})
const c = toRaw(count.value) // The value of ref is the proxy object
 Copy code
const count = reactive({
  a: 1,
})
const c = toRaw(count) // reactive objects do not require value
 Copy code
const roCount = readonly(count)
const c = toRaw(roCount)  //readonly object
 Copy code

markRaw

Mark an object so that it will never become a responsive proxy. For example, if you mount a third-party class library, the class library does not need to create a responsive. For example, if you add an additional attribute to a responsive object to display a list, the list is only for display, and there is no need to create a responsive to avoid performance waste

In vue2. If you append an attribute bar to a response number object foo, the update of foo.bar in the view will not be triggered. In this case, you need to use $set to append an attribute to foo

this.foo.bar =1 // Not updated
this.$set(this.foo,'bar',1) // Trigger update
 Copy code

However, in vue3, the proxy is used to intercept data. Its strength lies in that if a responsive object is defined and the attributes of the object are added or deleted, the appended attributes are still responsive and can still trigger the update of the view

const foo =reactive({})
foo.bar =1 // Trigger view update
 Copy code

However, vue3 such an approach will have another problem -- > in some cases, you do not want the additional data to become responsive. In this case, you need to use markRaw to wrap the object

const foo =reactive({a:1})
foo.bar ={b:1} // The bar attribute is still responsive
foo.bar =markRaw({c:1}) // Not responsive
 Copy code

customRef

Used to customize ref

  • Create a function package customRef, which is used to pass initial values and other formal parameter configurations
  • customRef is a function that receives two parameters: track tracker and trigger trigger
  • customRef returns an object with a get function and a set function in which the read and write operation logic is written
<input v-model="text" />
Copy code
// Create parameter package customRef to pass initial value
function useDebouncedRef(value, delay = 200) {
  let timeout
  // Return to customRef
  return customRef((track, trigger) => {
  // Returns an object with get and set functions
    return {
      // Read value operation
      get() {
        // Set up a tracker to track this value change 
        track()
        return value // Value
      },
      // Write value operation
      set(newValue) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          value = newValue // Blasphemy assignment
          trigger() // Trigger that tells the view to get data
        }, delay)
      }
    }
  })
}

export default {
  setup() {
    return {
      text: useDebouncedRef('hello') // use
    }
  }
}

Added by scmeeker on Thu, 04 Nov 2021 09:31:47 +0200