At the beginning

On September 19th, vue3.0 came as expected. In fact, many people have experienced it for a long time. However, I am lazy and cannot use it in the project because it has not been officially released, so I have not tried it. Its release now means that it is recommended for use on new projects. After all, its advantages over 2.0 are obvious, and while some of the accompanying tools are not yet complete, it should not be a problem to use it on small projects.

So far I have not actually used it, this article is summarized after reading its proposal document, API document and some articles, inevitably there will be problems, in addition, this article is similar to other similar articles introducing the VUE composite API, if you have read other articles can be ignored ~.

According to the official statement, vue3.0’s changes include performance improvements, smaller bundle sizes, better TypeScript support, and a new API for handling large-scale use cases. The new API refers to the composite API that is the focus of this article.

If your project doesn’t have or can’t upgrade to 3.0, don’t be sorry, you can use the 2.x version of the composite API in your project via the @vue/ composition-API plugin. This plugin provides some new interfaces in vue3.0 objects, and will upgrade to 3.0 in the future. Just change the reference from the plugin to the Vue object. There are some useful libraries (such as Vueuse, vue-Composable) that support both 2.x and 3.x versions, so feel free to use it.

React hooks. The reason why Vue was introduced is not because react hooks exist, so I have to have them. Copying is out of the question, frameworks are definitely moving in a more advanced direction. Such as the previous bidirectional binding, virtual DOM, and so on.

Personally, I have the following two problems in the previous use of 2.x:

In 2.x, vUE is mainly used for components and mixins. If the logical reuse does not involve templates and styles, mixins are generally used. However, mixins are very painful to use. Because after the code is extracted into a mixin, you can hardly remember what’s in it, there are multiple mixins and you don’t even know which one came from, you have to open the mixin file every time, and it’s easy to double declare the problem.

2. Although a component had better do one thing, but in fact it is more difficult, components are more or less have done many things, because in the writing of the vue is option organization type, data and data in a way and method, and so are other properties, so a relatively independent functions are scattered everywhere, it is difficult to distinguish, Extracting reuse logic is also cumbersome, which can be scary when a VUE file has a lot of code.

The advent of a composite API solves both of these problems, as well as making TypeScript type derivation more user-friendly.

In terms of usage, for vUE single files, the template part and the style part are basically the same as before, and the composed API mainly affects the logic part. Here’s the simplest example:

<template>
	<div @click="increment">{{data.count}}</div>
</template>
<script>
import { reactive } from 'vue'
export default {
    setup() {
        const data = reactive({
            count: 0
        })
        function increment() {
            data.count++
        }
        return {
            data,
            increment
        }
    }
}
</script>
Copy the code

One obvious change is that a setup function is added. The familiar data and methods attributes are removed. Note that all data used in the template should be explicitly returned in the setup function.

The example is small, but you can already see how it solves the above problem. For example, if you want to reuse this count, you just need to put:

const data = reactive({
    count: 0
})
function increment() {
    data.count++
}
Copy the code

You can extract it as a function, which is essentially a combination of things that were previously scattered among the options, plus the absence of this, so that each individual function can be extracted as a function. For differentiation, the function name usually starts with use, such as useCount. The setup function is essentially a constructor function or a generic init function in the code that organizes the code in a class manner, and is used to call the various use functions.

If you’re not used to this, the 2.x option is actually still available. The composite API is parsed before options, so properties in options cannot be accessed from the composite API. Properties returned by the setup function can be accessed from options through this, but it’s best not to mix them.

Common apis

setup

export default {
    setup() {
        return{}}}Copy the code

The setup function is a new option to use the combined API. It will be called before the beforeCreate lifecycle hook.

1. You can return an object whose properties are merged into the template rendering context;

2. Can return a function;

The first parameter is props. The second parameter is a context object that exposes some other commonly used properties.

reactive

import { reactive } from 'vue'
const data = reactive({
  count: 0,})Copy the code

Reactive makes an object reactive, returning data that is essentially the same as the data option.

watchEffect

import { reactive, watchEffect } from 'vue'
const data = reactive({
  count: 0,
})
watchEffect(() = > {
    alert(this.count)
})
Copy the code

WatchEffect is used to listen for changes in data. It executes immediately, then tracks all the reactive states used in the function, and re-executes the callback when it changes.

computed

import { reactive, computed } from 'vue'
const data = reactive({
  count: 0,})const double = computed(() = > {
    return data.count * 2
})
Copy the code

Equivalent to the computed option before, to create a state that depends on other states, note that it returns an object called ref:

{
    value: xxx// This is the value you need
}
Copy the code

The actual value referenced is the value property of the object, and the reason for doing this is simple, because computed is ultimately just a function, and if you return a value of a primitive type, such as 0, then double is still 0 even if data.count changes later, Because JavaScript is a base type that is passed by value, and objects are passed by reference, the value thus obtained is always the latest value.

In addition to passing getters, you can also pass an object with setter and getter properties to create a modified computed value.

ref

import { ref } from 'vue'
let count = ref(0)
Copy the code

In addition to using computed to return a REF, it can be created directly, but reactive can also be created directly:

let data = reactive({
    count: 0
})
Copy the code

Ref and Reactive have certain similarities, so you need to fully understand them to effectively select different methods in various scenarios. The most obvious difference between them is that ref needs to be evaluated through. Value, while Reactive does not.

The difference can also be understood as a REF provides responsiveness to a single piece of data, whereas reactive provides responsiveness to an entire object containing that data.

Using ref in templates and nested in reactive objects does not need to pass.value and will untangle itself:

<template>
	<div>{{count}}</div>
</template>
<script>
let data = reactive({
    double: count * 2
})
</script>
Copy the code

$refs. XXX is used to refer to the DOM element. This.$refs. XXX is used to refer to the DOM element.

<template> <div ref="node"></div> </template> <script> import { ref, onMounted } from 'vue' export default { setup() { const node = ref(null) onMounted(() => { console.log(node.value)// }) return {node}}} </script>Copy the code

toRefs

If you return a reactive object from a composite function, it will lose its responsiveness if you break it up and use it in the use function. To solve this problem, you can return it as it is:

import { reactive } from 'vue'
function useCounter () {
    let data = reactive({
        count: 0
    })
    return data
}
export default {
    setup() {
        // let {count} = useCounter()
        // return {, this is also not possible
        / /... useCounter()
        // }
        return {
            count: useCounter()// This will do}}}Copy the code

Another alternative is to use toRefs, which converts each attribute of a reactive object to a ref:

import { toRefs, reactive } from 'vue'
function useCounter () {
    let data = reactive({
        count: 0
    })
    return toRefs(data)
}
export default {
    setup() {
        let {count} = useCounter()
        return {
            count
        }
    }
}
Copy the code

It is useful to use toRefs to convert the data returned in the setup function:

import { toRefs, reactive } from 'vue'
export default {
    setup() {
        let data = reactive({
            count: 0
        })
        return {
            data
        }
    }
}
Copy the code

If so, use a value in the template that needs to be referenced by data.count, or if toRefs is used, use count directly:

<script> import { toRefs, reactive } from 'vue' export default { setup() { let data = reactive({ count: 0 }) return { ... toRefs(data) } } } </script> <template> <div>{{count}}</div> </template>Copy the code

Life cycle function

import { onUpdated, onMounted } from 'vue'
export default {
    setup() {
        onUpdated(() = > {
            console.log(1)
        }
        onMounted(() = > {
            console.log(1)}}}Copy the code

The created and beforeCreate hooks are removed. The created and beforeCreate hooks can only be used in the setup function.

In addition, there are other apis, and it is recommended to read through the official documentation in detail and then consolidate them in practice.

At the end

It takes a bit of getting used to using composite apis. You need to be able to distinguish ref and Reactive, not get confused between base and application types, get lost between reactive and non-reactive objects, and split up each use function. But it is also easier to write code that is harder to maintain, such as the huge length of setup functions.

To recap the upgrade idea, data in the data option is declared by Reactive. ToRefs () returns; Computed and Mounted are replaced by corresponding functions such as computed and onMounted. Methods can be declared anywhere, as long as the setup function is returned.

With this set of combined apis, the scope of use is not limited to VUE, but can be used in other places:

import { reactive, watchEffect } from '@vue/composition-api'
let data = reactive({
    count: 0
})
watchEffect(() = > {
    renderTemplate(data)// Your template rendering function
})
Copy the code

Well, that’s enough. I’m going to try it.

Refer to the article

vue-composition-api-rfc.netlify.app/zh/