preface

2020 is destined to be an extraordinary year. No matter the outbreak of the epidemic, the drastic fluctuations in the world situation, or the ups and downs of the stock market, I believe many Chinese people will feel grateful that I am A Chinese. As a technology curtilage, in addition to the outbreak, more female no melon or rain, with the launch of Vue3.0 Beta, everyone is scrambling to taste the fresh, the author is not exceptional also, after some research, feel Vue3 also exists its unique charm, it should also be convenient to write a blog has yet to experience friends quickly to a general cognition.

start

By default, you are familiar with Vue2.x

Environment set up

Related library versions

  • Vue-Cli 4.x
  • Vue 3.0.0 - beta. 1
  • Vue - the Router 4.0.0 - alpha. 7

The specific steps are as follows:

  1. useVueCliTo create aVueBasic Projects:vue create project
  2. In the project, execute the upgrade command:vue add vue-next

The project directory structure is as follows:

The basic environment is set up once you have done all of this correctly.

Configure the routing

According to the general specifications, create a router folder in the SRC directory and create the index.js file in the router folder.

Index. Js content:

import { createRouter, createWebHashHistory } from 'vue-router';
import Home from '.. /components/home'

const routes = [
    {path: '/'.redirect: '/home'},
    {path: '/home'.component: Home}
]

export default createRouter({
    history: createWebHashHistory(),
    routes
})

Copy the code

The basic routing configuration hasn’t changed much, most of the time you just need to focus on routing rule writing in routes. Next, we need to add the Router in main.js.

main.js:

import { createApp } from 'vue';
import App from './App.vue'
import router from './router';

const app = createApp(App);

app.use(router);
app.mount('#app');

Copy the code

Unlike the way we used new Vue() to create instances, Vue3 is changed here; Not only that, it is not difficult to find that the installation of routes from the previous vue.use (Router) into the above way, similarly for the Vuex access is also similar, the author here will not repeat much.

App.js

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>
Copy the code

Preliminary study on Basic Grammar

setup

The Setup feature is a new component option that acts as an entry point for using the Composition API (a new feature) within a component; When a component instance is created, it is called immediately after the initial item is resolved. In terms of life cycle, it is called before beforeCreate is mounted.

In general, when we need to use variables or calculate attributes, we will write:

home/index.vue

<template> <div class='home'> <div>{{count}}</div> <div>{{foo}}</div> </div> </template> <script> import { ref } from 'vue' export default { name: 'home', data() { return { count: 0 } }, computed: { foo() { return this.count + 1; }}};Copy the code

Both of them need to be classified into their own objects. In terms of the implementation of the same function, Vue3 is implemented as follows:

<template>
    <div class='home'>
        <div>{{count}}</div>
        <div>{{foo}}</div>
    </div>
</template>

<script>

import { ref, computed } from 'vue'

export default {
    name: 'home',
    setup(props, context) {
        const count = ref(0)
        const foo = computed(() => count.value + 1)
        return {
            count,
            foo
        }
    }
};
</script>

Copy the code

Do not panic, this part focuses on the setup entry function, the specific internal syntax can be ignored, later will be explained one by one.

Setup takes two important parameters:

  • Props: Sure, propsvue2thepropsThe important thing to note at this point is that we cannot deconstruct this parameter because using deconstruction would make it unresponsive. For example, the following code makespropsThe value passed in is not responsive:
export default { props: { name: String }, setup({ name }) { watchEffect(() => { console.log(`name is: '+ name) // Lose responsiveness! }}})Copy the code
  • This argument provides a context object that exposes an optional list of properties previously exposed by this in the 2.x API. It contains only three properties (attrs,slots,emit), for example:
setup(props, context) {
    context.attrs / / 2. X: enclosing attrs
    context.slots / / 2. X: enclosing slots
    context.emit / / 2. X: enclosing emit
}

Copy the code

After looking at the code, we can basically understand that the setup function is the entry point of the logical relationship and operation of the whole component. In Vue3, we use different API in the form of import, which is equivalent to we have more space to operate, have more freedom.

While Vue3 is backwards compatible with Vue2, it is important to note that we should try to avoid mixing the 2. X and setup functions, which can cause problems.

reactive

Reactive proxy that takes an object and returns the original object. This is equivalent to 2.x’s vue.Observable ().

The use of this API is better understood by the author in code:

<template> <div class='home'> <div>{{name}}</div> </div> </template> <script> import { reactive } from 'vue' export Default {name: 'home', setup() {const obj = reactive({name: 'star '}) obj.name = 'bilibili'; Return obj; }}; </script>Copy the code

You can see where this is going. Yes, the API is simply about making an object responsive.

ref

Accepts an internal value and returns a reactive and variable REF object. The ref object has a single property with.value pointing to an internal value.

In 3.x it has nothing to do with the ref on the label, and it has nothing to do with the $refs. See the template reference section for the new 2.x approach to dom acquisition.

Again, here’s an example:

<template> <div class='home'> <div>{{count}}</div> </div> </template> <script> import { ref } from 'vue' export default { name: 'home', setup() { const count = ref(0); count.value++; Console. log(count. Value); return { count }; }}; </script>Copy the code

Note that if you want to change a variable constructed using ref, you can only change xxx.value. Similarly, if you want to access the value in js, you must use xxx.value. If you assign a value to count++, you will get an error.

Estimates have friend to ask again here, that why we use {{count}} in the template template without access. Value, here you are in the use of interpolation expressions, inside it automatically, so we can use directly.

What would happen if we combined reactive with ref 😱. Here’s an example:

const count = ref(0)
const state = reactive({
  count
})

console.log(state.count) / / 0

state.count = 1
console.log(count.value) / / 1

Copy the code

When the REF is accessed or changed as a property of the reaction object, it automatically expands to an internal value, so it behaves like a normal property.

computed

This API is similar to 2.x. You can use getters and setters.

const count = ref(1)
const plusOne = computed((a)= > count.value + 1)

console.log(plusOne.value) / / 2

plusOne.value++ / / is invalid
Copy the code

It’s not hard to see here that it’s also accessed in the same way as ref, which also requires XXX. Value. At the same time, if you want to change the value of a evaluated property, you have to set the setter for it and change the dependencies accordingly. Without further ado, look at the code:

const count = ref(1)
const plusOne = computed({
  get: (a)= > count.value + 1.set: val= > {
    count.value = val - 1
  }
})

plusOne.value = 1
console.log(count.value) / / 0

Copy the code

readonly

This means that no matter how deep the object is nested, the object that is wrapped by it is always readable. In effect, it is a proxy:

const re = reactive({count: 0})
const readonlyRe = readonly(re);
readonlyRe.count++; // Invalid, and a warning is given
Copy the code

watchEffect

For this property, you can compare it to the 2.x watch object, which is meant to listen.

const count = ref(0)

watchEffect((a)= > console.log(count.value))
// -> Print 0

setTimeout((a)= > {
  count.value++
  // -- > Print 1
}, 100)

Copy the code

In short, it collects the dependencies of the functions you pass in, and if the dependencies change, it recalls the functions you pass in. Kids who used React hooks might say, “Oh, that’s useEffect.” Vue3 does borrow some nice designs from React, so, People should not think that plagiarism is not plagiarism. After all, the framework is to serve users. A good design should naturally be worth learning from, just like React can learn from some advantages of Vue to optimize itself.

Let’s go ahead and explore the API. When this API is called, it returns a function that suspends the handle, which we can explicitly call to stop the current listener, and for callbacks passed to watchEffect, the API will pass onInvalidate to register invalid callbacks when the call is triggered. Specific examples are as follows:

const stop = watchEffect(onInvalidate= > {
  const token = performAsyncOperation(id.value); // Perform an asynchronous operation
  onInvalidate((a)= > {
    // The id of the dependency has changed, but the asynchronous operation is not complete, we can stop your asynchronous operation here.
    token.cancel(); // Here we assume that your asynchronous operation returns a method that contains the cancel operation.
  })
})

stop(); // We can use this method to stop it

Copy the code

If we registered the invalid callback method, it will internally call the invalid callback for us when the dependency has changed but the asynchronous request has not completed.

Life cycle function

Here’s a comparison with 2.x:

  • BeforeCreate (deprecated by vue3) -> Use setup()
  • Created (deprecated by vue3) -> Use setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

Example:

import { onMounted, onUpdated, onUnmounted } from 'vue'

const MyComponent = {
  setup() {
    onMounted((a)= > {
      console.log('mounted! ')
    })
    onUpdated((a)= > {
      console.log('updated! ')
    })
    onUnmounted((a)= > {
      console.log('unmounted! ')}}}Copy the code

The template reference

After reading the introduction of this API in front of ref, very small partners will certainly be confused, then I want to get the DOM how to do, this Vue3 also has, relax, listen to the author continue to talk.

<template>
    <div class='home'>
        <div ref="dom"></div>
    </div>
</template>

<script>

import { ref, onMounted } from 'vue'

export default {
    name: 'home',
    setup() {
        const dom = ref(null)
        onMounted(() => {
            console.log(dom.value);
        })
        return {
            dom
        }
    }
};
</script>

Copy the code

From the code, we can see that the difference between this way of accessing the DOM and the previous way is that we need to set a responsive variable in the display and then set it in the template using the familiar ref=’ XXX ‘method.

At the end

After listening to the author’s narrative, do you have an idea of Vue3 that is eager to try 😜.

If you find anything I’ve misstated, please poke me in the comments section at 😝.