I’ve been busy with work recently, and I’ve fallen behind on improving my own capabilities, so I took the opportunity today to solve some of the problems I was thinking about before, and I also gave my VueBlog a chance to upgrade both vue and webpack to the latest beta version, and then I encountered a lot of pitfalls, so I’ll put them all on record today so I don’t forget them later.

VueBlog is currently using webpack5 + vue3 + vue-router-next + typescript build, the purpose is to replace the current hexo site, is also a static blog generator, but and hexo positioning is different, I use a single page design, rather than to each page to generate the corresponding html file, so it is not SEO friendly. So it’s not SEO friendly, we’ll figure it out later.

Upgrade Vue3

First use vue add vue-next to upgrade vue to the beta version. After execution vue will perform a conversion of the code, converting some api from the old version to the new one.

App

For example converting the code that creates the App object in main.ts to a new one, in vue2 we create the app object by new Vue() and call the $mount function to hang on to the element.

1
2
3
import App from "./App.vue";
const app = new Vue(App);
app.$mount('#app')

In vue3, the main idea is to do as much as possible through functions, because the type derivation can be done through the parameters and return values of the functions. In vue3, the creation of app objects is done through the createApp function, and then the dom elements are mounted through the mount function.

1
2
3
import App from "./App.vue";
const app = createApp(APp);
app.mount("#app");

Vur Router

If you are using a plugin like vue-router, there are some changes in the way you use it, and the router needs to be created by the corresponding create function. First you need to upgrade vue-router, the next version of vue-router is called vue-router-next. in vue-router, the function to create a router object is changed from VueRouter function to createRouter.

1
2
3
4
5
const router = new VueRouter({
    ...
});

export default router;

In vue3 it is necessary to use the new function to return.

1
2
3
4
5
const router = createRouter({
    ...
});

export default router;

The content has also been changed in part, you can visit the github repository to see the documentation

composition API

The core purpose of the composition api, a core feature proposed by vue3, is to initialize data scattered all over the place by integrating it into a setup function and relying on vue’s responsive data changes to complete the functionality.

The motivation for the composition api is in the RFC.

Better logic reuse and code organization

  1. As functionality grows, the code for complex components becomes increasingly difficult to read and understand. This is especially common when developers are reading code written by others. The root cause is that Vue’s existing API forces us to organize code by options, but there are times when it makes more sense to organize code by logical relationships.
  2. there is a lack of a clean and low cost mechanism to extract and reuse logic between multiple components

Better type derivation

Another common request from developers of large projects is better TypeScript support. vue’s current API has had a lot of trouble integrating TypeScript, mainly because vue relies on a simple this context to expose property, and the way we use this now is more subtle. (For example, the this of a function under the methods option points to the component instance, not the methods object).

In other words, Vue’s existing API was not designed with type derivation in mind, which makes adapting to TypeScript complicated. In contrast, the solution proposed in this RFC makes more use of common variables and functions that are naturally type-friendly. Code written with the API in this proposal will enjoy type derivation perfectly and will not require much additional type annotation.

This also means that the JavaScript code you write is almost TypeScript code. Even non-TypeScript developers will benefit from better IDE type support.

setup function is really comfortable to use, all the useful things can be put in one piece, the code is also convenient to organize, unlike the previous need to be scattered into a variety of hook and calculate properties, data functions. However, there is also a place where I am not comfortable with it, basic types and objects need to use the ref function and reactive function for packaging, sometimes there are all kinds of trouble with it, need to pay more attention to some. However, this is not a big problem, and when writing C++, all the objects are wrapped with smart pointers, you will get used to it after using it more.

This is a vue2 classic example, through the data function and calculate the property to return different data.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
export default new Vue({
    data: function() {
        return {
            message: "hello"
        }
    },
    computed: {
        reversedMessage: function () {
            return this.message.split('').reverse().join('');
        }
    }
});

In vue3 it can all be centralized to the setup function and returned together, and the template can be used directly.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import { ref, computed } from "vue";

export default {
    setup() {
        const message = ref("hello");
        const reversedMessage = computed(() => {
            return message.value.split('').reverse().join('');
        });

        return { message, reversedMessage };
    }
};

It can be seen that the use of the setup function can return a piece of content required by the template, the structure is clearer, vue2 pattern is also possible, but the focus is not the same, vue2 purpose is a kind of action data should be put in a piece, and vue3 setup function is the data processing are put in a piece, so that the organization of the data is more convenient and centralized.

Props

Props are custom properties registered on a component. When a value is passed to a props, it becomes a property of that component.

1
<hello v-bind:message="message" />

The hello component can receive custom properties by defining props functions.

1
2
3
4
5
export default new Vue({
    props: {
        message: String
    }
});

This allows you to use the message property in helle.vue, but it is important to note that the hello component does not modify the message passed in, otherwise it will break the flow of data.

It is easier to use in vue3 because the type derivation is more convenient.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
interface Props {
    message?: String
}

export default {
    props: {
        message: {
            type: String,
            require: false,
            default: "",
        }
    },
    setup(props: Props) {
        const reversedMessage = computed(() => {
            if (props.message === undefined) {
                return String;
            }

            const innerMessage = props.message;
            return innerMessage.split('').reverse().join('');
        });

        return { reversedMessage };
    }
};

Using props in vue3 and typescript requires some attention. Firstly, the value in props needs to be set to possibly empty, otherwise the signature of the setup function will not match. Secondly, to access the props data you need to turn on the props parameter of the setup function, and a context parameter to access the contextual content.