Writing in the front

Before we try Vue3, let’s take a look at what makes Vu3 great.

There are 6 features in total:

  • Performance (About 2 times faster than vue2 Runtime)
  • Tree Shaking Support
  • Better TypeScript Support
  • Composition API
  • Custom Renderer API
  • Fragment, Teleport, Suspense

1. Vue3 origin setup

  1. Understanding: The composite API arena for Vue3.0 is setup
  2. Setup All data methods and so on are configured in setup
  3. Setup has two return values:
    1. If an object is returned, the attributes and methods in the object can be used directly in the template
    2. If you return a render function, you can customize the render content
  4. Note:
    1. Do not mix VUe3.0 with vue2 configurations
    2. Vue2 configurations (data, methods, computed, and so on) are setup property methods that can access VUe3
    3. Configurations that do not access VUe2 in SETUP (data, methods, computed, and so on)
    4. If the names are the same, vue3 prevails
  5. Setup cannot be an async function because the return value is no longer a return object, but a promise, and the template does not see properties in the return object.

2. Ref function

  • Function: Used to define a reactive data
  • Grammar:const name = ref(initValue)
    • Create a reference object that contains responsive data.
    • Operating data in js:name.value
    • Read data from template: do not need value, direct<div>{{name}}</div>
  • Note:
    • Accepted data: base type, object type
    • Basic data types: reactive is dependentObject.defineProperty()thegetwithsetSet and value operations
    • Object type data: Internally uses a new function in VUe3 —reactiveFunction (essentially proxy proxy)

3. The reactive function

  • Function: Used to define reactive data of an object type (do not use it for basic types, use ref instead)
  • Grammar:Const proxy = ReactiveTake an object or array and return a proxy object (instance object of proxy, proxy object for short)
  • Reactive defines responsiveness as “deep”, with all objects in an object being responsive
  • Internal Es6-based proxy implementation, through the internal data of the proxy object to operate

Objects processed by reactive cannot use deconstruction syntax because they will lose their responsiveness. You can use toRefs to convert every attribute of reactive toRefs for reactive processing.

Difference between REF and Reactive

Reactive is used to convert object data into responsiveness, similar to an Observable in VUe2, while ref is used to convert individual or underlying data types into responsiveness.

Let’s explain why vue3 has two apis for converting data into responsive data:

  • Ref takes an internal value and returns itaA reactive and mutable REF object with a single reference to an internal valueproperty.value
  • Reactive takes an object and returns a reactive copy of the object that converts every element in it to a REF object

In a nutshell, Reactive converts object data to reactive, converting every element in an object to ref-responsive data. Ref, on the other hand, can not only convert object data into responsive, but also handle the underlying data types (String, Boolean, and so on).

The difference is due to the fact that responsivity in VUe3 is implemented based on a proxy, and the target for a proxy must be a reference data type, that is, an object stored in heap memory that is referred to by a pointer. The reason for this is that simple datatypes are completely new data each time they are assigned, so it is difficult to implement the responsiveness of simple datatypes.

What if we wanted to get a response for a simple data type?

Vue3 also allows for reactive processing of simple data types through ref. Ref attaches values to value by creating internal state, so objects generated by ref are retrieved and used by.value. Overriding get/set listeners and handling objects relies on Reactive.

As such, a REF can handle both simple data types and reference data types in a reactive manner. In practice, you should avoid declaring all variables on top of reactive as data for VUe2, and instead declare them close to your application and logic.

class RefImpl<T> {
  private _value: T

  public readonly __v_isRef = true

  constructor(private _rawValue: T, public readonly _shallow = false) {
    this._value = _shallow ? _rawValue : convert(_rawValue)
  }

  get value() {
    track(toRaw(this), TrackOpTypes.GET, 'value')
    return this._value
  }

  set value(newVal) {
    if (hasChanged(toRaw(newVal), this._rawValue)) {
      this._rawValue = newVal
      this._value = this._shallow ? newVal : convert(newVal)
      trigger(toRaw(this), TriggerOpTypes.SET, 'value', newVal)
    }
  }
}
...
const convert = <T extends unknown>(val: T): T =>
  isObject(val) ? reactive(val) : val
...
Copy the code

4. Responsivity principle in Vue3

  • Response formula principle of VUE2:
    • Object type: PassObject.defineProperty()Interception of reading and modifying properties (data hijacking)
    • Array types: Interception is implemented by overriding a series of methods that update an array. (Wrap array change methods)
  Object.defineProperty(data,"count", {get(){},
    set(){}})Copy the code
  • Existing problems:
    • The interface is not updated when you add or delete attributes
    • Modify the array directly through the following table, the interface does not automatically update
  • The responsivity principle of VUE3
    • Proxy: Intercepts the change of any property of an object, including reading and writing property values, adding or deleting property values
    • Reflect: Operates on the properties of the proxied object

5. Differences between Reactive and REF

  • Define the data
    • Ref: Used to define base data types
    • Reactive: Used to define reference data types
    • Note: REF can also be used to define reference data types that are automatically converted internally to proxy objects via RActive
  • The principle of
    • Ref:Object.defineProperty()Set and GET properties for reactive (data hijacking)
    • Reactive:ProxyTo implement reactive (data hijacking) and Reflect the internal data of the object
  • use
    • Ref: Data defined by ref needs to pass.valueThis operation is not required when the template reads data.value
    • Reactive: Data defined by reactive is not required.value, can be set and read

6. Calculate properties and monitor

  • This function is consistent with computed configuration in VUE2
  • Writing:
import {computed} from "vue";
setup(){
  const sum = computed(() = >{
    returnnum1 + num2; })}Copy the code
import {computed,reactive} from "vue"
setup(){
  const person = reactive({
    firstName:"wen".lastName:"bo"
  })
  / / short
  let fullName = computed(() = >{
    return person.firstName + "-" + person.lastName;
  });
  
  / / complete
  let fullName = computed(() = >{
    get(){
      return person.firstName + "-" + person.lastName;
    },
    set(value){
      const newArr = value.split("-");
      person.firstName = nameArr[0];
      person.lastName = nameArr[1]; }})}Copy the code

7. Watch function

  • This function is consistent with that of Watch in VUe2
  • Note:
    • When monitoring reactive data defined by Reactive, oldValue cannot be obtained correctly, forcing deep monitoring (deep configuration fails)
    • The deep configuration is effective when monitoring a property in reactive data defined by Reactive

let person = reactive({
  name:"wenbo".age:18.job: {job1: {salary:20}}})// Monitor reactive data defined by ref
watch(sum,(newValue,oldValue) = >{
  console.log("The sum changed",newValue,oldValue); }, {immediate:true})

// Monitor reactive data defined by multiple refs
watch([sum,msg],(newValue,oldValue) = >{
  console.log("Sum or MSG has changed.",newValue,oldValue);
})

If watch is monitoring reactive data defined by Reactive, oldValue cannot be obtained correctly. If Watch is monitoring reactive data defined by Reactive, deep monitoring is disabled */
watch(person,(newValue,oldValue) = >{
  console.log("Perosn changed",newValue,oldValue); }, {immediate:true.deep:false})

// Monitor a property in reactive data defined by Reactive
watch(() = >person.age,(newValue,oldValue) = >{
  console.log("The age of person has changed.",newValue,oldValue)
})

// Case 5: Monitor some properties in reactive data defined by Reactive
watch([() = >person.name,() = >person.age],(newValue,oldValue) = >{
  console.log("Person's name or age changed",newValue,oldValue)
})

// Special case - the property of the listening object is still an object
watch(() = >person.job,(newValue,oldValue) = >{
  console.log("Person's job has changed.",newValue,oldValue)
},{deep:true})
Copy the code

Note:

  • Watch listens to objects defined by Reactive in five ways

  • Watch listens for reactive data defined by ref in two cases:

    • Ref defines data of the basic type, and cannot be evaluated.valueListen in. Such asconst num = ref(0)At this point tonum.valueNum (0) = num (0) = num (0)
    • Ref defines the object data type, and the data processed by REF is of the REF instance. To listen for changes to an object, the.valueTo listen in becauseRef object. The valueIt is a reactive data proxy processed by Reactive.

8. WatchEffect function

  • Watch routine: Specify both the monitoring properties and the monitoring callbacks
  • The watchEffect formula: You don’t have to specify which property you are monitoring, but you monitor which property is used in the monitoring callback
  • WatchEffect is something like computed:
    • Computed focuses on the computed value, the return value of the callback function, so you have to write the return value
    • WatchEffect focuses on the calculation, the function of the callback function, so you don’t have to write the return value
let person = reactive({
  name:"wenbo".age:18.job: {job1: {salary:20}}})// If the data used in the warchEffect callback changes, the callback is reexecuted
watchEffect(() = >{
  const x = person.name
  const y = person.job.job1.salary
  console.log("WatchEffect triggered")})Copy the code

9. Customize hooks functions

  • Hook function: Essentially a function that encapsulates the composite API used in the setup function
  • Similar to mixins in VUE2
  • Benefits: Reuse code, making logic in SETUP clearer and easier to understand
<div>PageX: {{point.pageX}}, pageY: {{point.pageY}}<div>
  

Copy the code

Hooks file usePoint. Js

import {reactive} from "vue"

const handleClickPoint = () = >{
  // Implement mouse "click" related data
  let point = reactive({
    pageX:0.pagey:0
  })
  
  // Implement mouse "dot" related methods
  const handlePoint = (event) = >{
    point.pageX = event.pageX;
    point.pageY = event.pageY;
    console.log(event.pageX,event.pageY)
  }
  // Implement the mouse dot related periodic function
  onMounted(() = >{
    window.addEventListener("click",handlePoint)
  })
  
  onBeforeUnmounted(() = >{
    window.removeEventListener("click",handlePoint)
  })
}
Copy the code

10. ToRef function

  • Objects processed by Ref and Reactive cannot be processed directly using deconstruction, otherwise they will lose their responsiveness
  • Creates a ref object whose value points to an attribute in another object
  • Grammar:const name = toRef(person,"name")
  • Application: When an attribute in a reactive object is individually provided for external use
  • Extension: toRefs has the same functionality as toRef, but can batch create multiple REF objects, syntax:toRefs(person)

11. VUE3 life cycle

Other composite apis

1. shallowReactive与shallowRef

  • ShallowReactive: reactive that deals only with the outermost properties of an object (shallowReactive)
  • ShallowRef: Only primitive data type responsivity is handled, not object responsivity
  • Time of use:
    • If you have an object data, the structure is deep, but changes only when the outer properties change == shallowReactive
    • If there is an object data, the subsequent functionality does not modify the properties in that object, but instead generates a new object to replace == shallowRef

2. With shallowReadonly readonly

  • Readonly: make responsive data read-only (deep readonly)
  • ShallowReadonly: Make responsive data read-only (shallow read-only)
  • Application scenario: Data is not modified

3. toRaw与markRaw

  • toRaw
    • Function: Transforms a reactive object generated by Reactive into a normal object
    • Usage scenario: It is used to read the common object corresponding to the responsive object. All operations on this common object do not cause page updates
  • markRaw
    • Function: Marks an object so that it will never be called a reactive object
    • Application Scenarios:
      • Some values should not be set to be responsive, such as complex third-party libraries
      • Skipping reactive transformations can improve performance when rendering large lists with immutable data sources

4. customRef

  • What it does: Creates a custom REF with explicit control over its dependency trace and update trigger
  • Example:

  <template>
    <input type="text" v-model="str"/>
    <h1>Current value: {{STR}}</h1>
  </template>

    <script>
    import {ref, customRef} from "vue";
    export default {
      setup(){
        // define a ref: myRef
        const myRef = (value) = >{
          return customRef((track,trigger) = >{
            return{
              get(){
                console.log('Someone has read this data from myRef${value}`);
                track();
                return value;
              },
              set(newValue){
                console.log('Someone changed the myRef data to new data${newValue}`);
                value = newValue;
                trigger();// Tell vue to reparse the template}}}); }const str = myRef("hello");
        return{
          str
        }
      }
    }
    </script>

Copy the code

5. Dojo.provide and inject

  • Function: Implements communication between parent and grandson components
  • Application scenario: The parent component has a provide option to provide data, and the child component has a Inject to obtain usage data

6. Judgment of responsive data

  • IsRef: Checks whether a value is a REF object
  • IsReactive: A reactive agent that checks whether a value is created by Reactive
  • IsReadonly: Checks whether an object is a read-only proxy created by readOnly
  • IsProxy: Checks whether an object is a proxy created by Reactive or Readonly

Vue3 uses hook points

  1. There are asynchrony problems in hooks

In fact, it can be found in the use that hook is essentially a function for extraction with relatively high flexibility. However, when it comes to asynchronous logic, a lack of comprehensive consideration will lead to many problems. Hooks can override asynchrony, but must not be blocked when a valid object is returned when executed in SETUP.

There are generally two styles of asynchrony:

  • There are no external dependencies, just render response variables to deliver. In this case, the response variable can be declared, exposed, and asynchronously modified in the hook.

  • External dependencies need to be processed on the use side. In this case, the Promise can be exposed to the outside world to obtain the ability of synchronous operation.

  1. The problem of this

Because setup is between the beforeCreate and Created phases of the lifecycle, this cannot be retrieved. Of course, we can get some capabilities similar to this through the second context parameter of setup, but the ability to manipulate routing, vuex, etc is limited. For this reason, the latest router@4 and vuex@4 provide combinatorial apis.

Because vue2’s underlying limitations make it impossible to use these hooks, you can obtain some operational capability by referring to an instance or by using getCurrentInstance to get an object mounted on a component instance.

Although the responsivity principle of the composite API overwrites attributes through Object.defineProperty, which is the same as vUE’s responsivity principle, the implementation is different and therefore does not communicate with vue’s native responsivity in SETUP. As a result, there is no way to listen for their responses even if you get the corresponding instances, you can only use them in the option configuration.

Common components in VUE3

1. The Fragment components

In VUe2: Components must have a root tag

In VUE3, components can have no root tag, and have multiple tags wrapped inside the Fragment virtual element

Benefits: Reduced label hierarchy, reduced memory footprint

2. Teleport

Teleport relies on technology that can move a component’s HTML structure to a specified location

Syntax:

main.vue

<div name="modal"></div>
<Modal :isOpen="isOpen" @closeModal="closeModal"/>
<button @click="openModal" >open modal</button>
Copy the code

modal.vue

 <teleport to='#modal'>
    <div class="modal-box" v-if="isOpen">
      <slot>this is a modal</slot>
      <button @click="handleCloseModal">close</button>
    </div>
  </teleport>
Copy the code

3. suspense

Render some extra content while waiting for asynchronous components to make the application a better user experience.

Use steps:

  1. Asynchronously importing components

  2. Wrap components in Suspense and configure default and fallback.


import {defineAsyncComponent} from "vue"
const child =defineAsyncComponent(() = >import("./components/child.vue"))
Copy the code

Refer to the article

  • Vue3 official website
  • Composition-api Practice Summary

Write in the last

Thank you for reading, I will continue to share with you more excellent articles, this article reference a large number of books and articles, if there are mistakes and mistakes, hope to correct.

More latest articles please pay attention to the author nuggets a sichuan firefly account and the public number front gravitation.