Vue3 Composition-API

This article takes a brief look at how the Vue3 composite API is currently used and what it means.

Of course, the time to ridicule or ridicule, hey hey

1. Component status

Using 2.x as an example, we are most concerned about the form of two-way data binding:

<template> < button@click ="increment"> {{ state.double }} </button> </template> <script> import { computed, reactive } from 'vue' export default { setup() { const state = reactive({ count: 1, double: computed(() => state.count * 2) }) function increment() { state.count++; } return { state, increment } } } </script>Copy the code

Reactive, a reactive proxy that receives a common object and returns that object, is equivalent to vue.Observable () in 2.x.

Reactive transformations are “deep” : they affect all nested properties inside the object. Proxy-based implementations return a Proxy object that is not equal to the original object. Try to use proxy objects instead of relying on original objects.

The essence of a Vue responsive system: When an object is returned from data() in a component, it is essentially made reactive internally by calling Reactive ().

Computed, passing in a getter function returns a ref object that cannot be manually modified;

Another way to use computed is to pass in a function object with get and set to create a computed state that can be modified manually.

const double = computed({

    get(a)= > count.value,

    set(val) = > {

        count.value = val * 2

    }

})

Copy the code

WatchEffect tracks the reactive state used during execution as a dependency (similar to the Watch option in 2.x, but without separating the dependent data source from the side effect callbacks) and rerunks the function when the dependency changes. When a component’s Setup () or lifecycle hook is called, watchEffect is linked to the component’s lifecycle and stops automatically when the component is uninstalled.

A new ref, which takes a parameter value and returns a responsive and mutable REF object. The ref object has a single attribute that points to an internal value, which is.value.

<template> < button@click ="increment"> </button> <p>{{num}}</p> </template> <script> import {ref} from 'vue' export default { setup() { const num = ref(0); function increment() { num.value ++; } return { increment, num } } } </script>Copy the code

If an object is passed to a REF, the reactive methods are called for the deep response transformation.

Readonly, passing in an object or ref, returns a read-only proxy for the original object. Even for deep objects, any properties inside are read-only.

const original = reactive({count0});

const only = readonly(original);

watchEffect((a)= > { // Rely on tracing

    console.log(only.count);

})

original.count ++; // Changes here will trigger monitoring of ONLY

only.count ++;  // Cannot modify and issue a warning

Copy the code

So far the introduction has covered the pure state aspects of components: reactive state, computed state, and state changes as user input. The life cycle and composite apis will be introduced next.

2. Lifecycle hooks

import {

    onMounted, onUpdated, onUnmounted

from 'vue'

setup() {

  / /...

        onMounted((a)= > {

            console.log('Component is already mounted! ')

        })

     onUpdated((a)= > {

        console.log('Component has been updated! ')

     })

     onUnmounted((a)= > {

        console.log('Component has been uninstalled! ')

     })

        / /...

}

Copy the code

As shown in the previous example, lifecycle hook functions can only be registered with setup functions because they rely on internal global state to locate the current component instance (that is, the component instance that is calling Setup ()) and will throw an error if not invoked by the current component.

Component instance contexts are set during lifecycle hook synchronization execution, so synchronously created listeners and computed state are removed when the component is uninstalled.

As shown above, there are hooks: onBeforeMount, onBeforeUpdate, onBeforeUnmount, onErrorCaptured and the new ones onRenderTracked and onRenderTriggered.

3. Composite apis vs. optional apis

Organized code ultimately makes code more readable and easier to understand. Instead of “This component has these data, these properties, and these methods,” you see “what does this component do?” Option-based apis write code that does not express the functionality of the component well.

When developing with an optional API, for example, it is difficult to tease out the logic by reading the code in the options because the code associated with the logic is scattered all over the place. This fragmentation makes reading and maintenance difficult, and the forced separation of options raises the bar for logical understanding, forcing us to jump back and forth between blocks of code to find relevant code.

Conversely, it would be nice to put the same logical point code together. That’s exactly what composite apis do. This pattern allows the component’s logical points to end up as well-decoupled functions: each logical point code block is grouped into a single function, greatly reducing the need to jump back and forth. You can also fold these composite functions to make it easier to navigate:

In addition to the extraction logic, another change is the reference to this.

This in setup() is completely different from this in 2.x, and using this in both setup() and 2.x would be confusing. Here we need to introduce the setup function again:

  • When a component instance is created, the props function is initialized, followed by the setup function, which is called before the beforeCreate.

  • Setup returns an object whose properties are merged into the context of the component template;

  • The first argument to setup is props;

  • The second argument to setup provides the context object and optionally exposes some properties from 2.x.

export default {

    props: {

        name: string,

        age: number

    },

    setup(prop,context) {

        watchEffect((a)= > {

            console.log(`My name is ${props.name},I'm ${props.age} years old.`)

        });

        context.attrs

        context.slots

        context.emit

    }

}

Copy the code

When extracting a logical point, the logical method can also accept parameters props and context:

const checkUsername = (props, context) = > {

  onMounted((a)= > {

    console.log(props)

    context.emit('event'.'payload')

  })

}

export default {

  setup (props, context) {

    checkUsername(props, context)

  }

}

Copy the code

4. The last

Hopefully this article will help you get a better idea of how the Composition API will change the way we code, improve code readability and cohesion coupling as we move forward, which is what mature programmers do.