Download as pdf or txt
Download as pdf or txt
You are on page 1of 20

4/1/2020 How to migrate from Vue 2.0 to Vue 3.

0 Composition API with TS (Part 2: Replace)

How to migrate from Vue 2.0 to Vue 3.0


Composition API with TS (Part 2:
Replace)
Toru Eguchi Follow
Dec 22, 2019 · 7 min read

This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 1/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

Vue3.0 Updates from Evan You in VueFes Japan 2018

In October 2019, Vue 3.0 pre-alpha was finally released. So it’s the matter of
time to use Vue 3.0 as production.

To prepare for it, I would like to share how to migrate from Vue 2.0 to Vue
3.0. Because these days large amount of Vue users has already introduced
TypeScript, this article also use TypeScript.

There are 3 steps on the migration like below.

1. Injection of Vue 3.0 into Vue 2.0

2. Replace Vue 2.0 codes to Vue 3.0

3. Create a global store with Vue 3.0 composition API

Because the topic is bit long, I splitted it into 3 articles. This article is the
continuation of the first step. If you want to start from the specific part, feel
This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 2/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

free to proceed to the page.

Replace Vue 2.0 codes to Vue 3.0


You already setup Vue 3.0 composition API in the previous article! So Let’s
replace Vue 2.0 code with Vue 3.0 gradually !

Use createComponent and setup() instead of Vue.extend


In Vue 2.0, “Vue.extend” is used to let TypeScript properly infer types inside
Vue component. Instead of “Vue.extend”, you must use createComponent in
Vue 3.0 for type inference. In addition, inside of createComponent, you
should use setup function which is an entry point where composition
functions are invoked.

// src/List.vue

<script lang="ts">
import { createComponent } from "@vue/composition-api";

export default createComponent({


setup(){
// DO SOMETHING HERE
}
This is your
}) last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 3/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

But when you replace Vue.extend to createComponent, you have many


errors in your editor because createComponent doesn’t know this in Vue
2.0. You have many compile errors in the terminal.

This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 4/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

But Don’t worry. This error is from Vetur. Everything works fine.

Replace Vue 2.0 “data” by using reactive


Next step is replacing local state of Vue 2.0, data . It’s super simple, use
reactive inside of setup function like below.

// src/List.vue

<script lang="ts">
import { FilterByEnum, Data, FilterBy } from "./types/List";
import { createComponent, reactive } from "@vue/composition-api";

export default createComponent({


setup(){
const todoState = reactive<Data>({
todos: [],
newTodo: "",
filterBy: FilterByEnum.ALL
});
}
})

This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 5/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

reactive is the equivalent of the current Vue.observable() in Vue 2.0.


Returned value from reactive is a reactive object which you like.

Actually, you have different API to make variables reactive called ref() .
But the function itself is pretty similar to reactive() . Please check the

official documentation for it.

Replace Vue 2.0 “methods” !


Methods in Vue2.0 become simple functions inside setup function. It’s
easier to see the codes. Let’s get todos first.

// src/List.vue

...
import todos from "../utils/todos";

export default createComponent({


setup(){
const todoState = reactive<Data>({
...
const init = function(): void {
getTodos();
};
const getTodos = function(): void {
setTimeout(() => {
This is your last freetodoState.todos = [...todos];
story this month. Sign up and get an extra one for free.
}, 1000);
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 6/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

}
})

Because you don’t have to use this to access local state, it’s simpler.

So far, you have the function to initialize todos. But when do you call it ?
Yes, you want to do it when Vue instance is “Mounted”.
Of course Vue 3.0 has lifecycle hooks. You should use it like below.

// src/List.vue

...

export default createComponent({


setup(){
const todoState = reactive<Data>({
...
onMounted(() => {
init();
});

const init = function(): void {


getTodos();
};

const getTodos = function(): void {


setTimeout(() => {
This is your last free story this month. Sign up and get an extra one for free.
todoState.todos = [...todos];
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 7/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

}, 1000);
}
})

You can move rest of methods to inside setup function. After moving all
method, List.vue becomes like below.

// src/List.vue

<script lang="ts">
import Vue from "vue";
import todos from "../utils/todos";
import { FilterByEnum, Data, FilterBy } from "./types/List";
import { createComponent, reactive, onMounted } from
"@vue/composition-api";

export default createComponent({


setup(props, context) {
const todoState = reactive<Data>({
todos: [],
newTodo: "",
filterBy: FilterByEnum.ALL
});

onMounted(() => {
init();
});

const init = function(): void {


getTodos();
This is your last
};
free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 8/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

const getTodos = function(): void {


setTimeout(() => {
todoState.todos = [...todos];
}, 1000);
};
const addTodo = function(): void {
const newTodo = { name: todoState.newTodo, completed: false };
todoState.todos = [...todoState.todos, newTodo];
todoState.newTodo = "";
};
const deleteTodo = function(index: number): void {
todoState.todos = todoState.todos.filter((todo, i) => i !==
index);
};
const completeTodo = function(index: number): void {
todoState.todos[index].completed = true;
};
const handleClickFilterBy = function(filterBy: FilterBy): void {
todoState.filterBy = filterBy;
};
const goEditTodo = function(index: number): void {
context.root.$router.push(`/todos/${index}/edit`);
};
},

One thing you don’t know yet is, two arguments of setup, props and context.
Props is easy to understand. You can get a props inside of setup function. In
the context, you can check many things which is seen in this of Vue 2.0 like
slot , parent and root .

So if you want to use $router , you can access from context.root .


This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 9/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

Replace “computed” of Vue 2.0


You already noticed that you have Vue2.0 codes only in computed. But it’s
also super easy to replace.

// src/List.vue

...

import { createComponent, reactive, onMounted, computed } from


"@vue/composition-api";

export default createComponent({


setup(props, context) {
const todoState = reactive<Data>({
todos: [],
newTodo: "",
filterBy: FilterByEnum.ALL
});

const filteredTodos = computed(function() {


return todoState.todos.filter(todo => {
if (todoState.filterBy === FilterByEnum.WORKING) {
return !todo.completed;
}
if (todoState.filterBy === FilterByEnum.DONE) {
return todo.completed;
}
return todo;
});

This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 10/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

const numOfTodos = computed(function(): number {


return todoState.todos.filter(todo => !todo.completed).length;
});

...

You can import computed from @vue/composition-api . And just like


methods, you can declare the name of computed and pass computed logic
to an argument of computed. That’s it.

If you want to use variables, methods in templates


So far, you have replaced all Vue 2.0 codes to Vue 3.0’s one. This todo app
uses many variables and methods inside of template like below.

State
- todos
- newTodo
- filterBy

Computed
- filteredTodos
- numOfTodos
This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 11/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

methods
- addTodo
- deleteTodo
- completeTodo
- handleClickFilterBy
- goEditTodo

But if you want to use them inside template, what you should do ? It’s really
easy. Just return what you need inside setup function.

// src/List.vue

// Inside of template, nothing changed.

...

import { createComponent, reactive, onMounted, computed, toRefs }


from "@vue/composition-api";

export default createComponent({


setup(props, context) {
...
return {
...toRefs(todoState),
filteredTodos,
numOfTodos,
This is your last free story this month. Sign up and get an extra one for free.
addTodo,
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 12/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

handleClickFilterBy,
completeTodo,
goEditTodo,
deleteTodo
};
}
})

One thing you don’t know is toRefs . It’s because when you use reactive

without reRefs , you must use them inside temple like todoState.todos ,
todoState.filterBy . But it’s not DRY ! With toRefs() and destructuring,
you can use them same as before.

So now, everything works properly !

Make it composable
So far, Vue 3.0 is perfectly works. But you can refactor it. The big purpose of
Vue 3.0 composition API is to make codes composable. It means that code
should be separated in small parts and make them use again and again.

So let’s compose todo functions.

1. Make a function called useTodos outside of export default.


This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 13/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

// src/List.vue

...

import { createComponent, reactive, onMounted, computed, toRefs }


from "@vue/composition-api";

export default createComponent({


setup(props, context) {
...
}
})

const useTodos = () => {}

2. Copy and paste functions and state inside setup to useTodos

Because goEditTodo is bit different, you don’t have to move it.

// src/List.vue

...

import { createComponent, reactive, onMounted, computed, toRefs }


from "@vue/composition-api";

This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 14/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

export default createComponent({


setup(props, context) {
const goEditTodo = function(index: number): void {
context.root.$router.push(`/todos/${index}/edit`);
};
return {
goEditTodo
};
}
})

const useTodos = () => {


const todoState = reactive<Data>({
todos: [],
newTodo: "",
filterBy: FilterByEnum.ALL
});

...

return {
...toRefs(todoState),
filteredTodos,
numOfTodos,
addTodo,
handleClickFilterBy,
completeTodo,
deleteTodo
}
}

This useTodos function is called a composition function.

This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 15/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

3. Call useTodos inside setup and use it.

// src/List.vue

...

import { createComponent, reactive, onMounted, computed, toRefs }


from "@vue/composition-api";

export default createComponent({


setup(props, context) {
const goEditTodo = function(index: number): void {
context.root.$router.push(`/todos/${index}/edit`);
};

return {
...useTodos(),
goEditTodo
};
}
})

const useTodos = () => {


...

return {
...toRefs(todoState),
filteredTodos,
numOfTodos,
addTodo,
handleClickFilterBy,
completeTodo,
This is your last free story this month. Sign up and get an extra one for free.
deleteTodo
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 16/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

}
}

Now it works perfectly !

4. Separate the composition function to other file.

Because composition function is just a function, you can easily separate it.
From Linus Borg’s demo repo, those composition functions are saved to
src/composables/ . And each composition functions are named like useHoge

like below. Actually, the type file is also moved to under composables.

// composables/useTodos.ts
import todos from "../utils/todos";
import { FilterByEnum, Data, FilterBy } from "./types/UseTodos";
import { reactive, onMounted, computed, toRefs } from
"@vue/composition-api";

export const useTodos = () => {


...
};

And import it to List.vue .


This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 17/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

// src/List.vue
<script lang="ts">
import Vue from "vue";
import { createComponent } from "@vue/composition-api";
import { useTodos } from "../composables/useTodos";

export default createComponent({


setup(props, context) {
const goEditTodo = function(index: number): void {
context.root.$router.push(`/todos/${index}/edit`);
};
return {
...useTodos(),
goEditTodo
};
}
});
</script>

Now, List.vue is super clean. With Compostion API, you can separate logics
from vue component and vue component can focus more on View. That’s
the one big value of Vue 3.0.

Next Level
So far, the composition function is called in List.vue component. What if you
call same composition function in Edit.vue ? Are the states and functions
shared between components ??
This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 18/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

The answer is “NO”. Because composition function is just a function, you


must use something to share them globally. Composition function is not
state management like Vuex.

But if you use Provide and Inject of Vue, you can create global store. So next
article explains how to create global store with Vue 3.0.

. . .

In this article, I explained how to replace Vue 2.0 to Vue 3.0. But this article
doesn’t talk about global store of Vue yet. I would like to share the
possiblity of Vue 3.0 global store and try to make it.

1. Injection of Vue 3.0 into Vue 2.0

2. Replace Vue 2.0 codes to Vue 3.0 (Now here !)

3. Create a global store with Vue 3.0 composition API

JavaScript Vuejs Vuejs 3 Front End Development

This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 19/20
4/1/2020 How to migrate from Vue 2.0 to Vue 3.0 Composition API with TS (Part 2: Replace)

Discover Medium Make Medium yours Become a member


Welcome to a place where words matter. Follow all the topics you care about, and Get unlimited access to the best stories
On Medium, smart voices and original we’ll deliver the best stories for you to on Medium — and support writers while
ideas take center stage - with no ads in your homepage and inbox. Explore you’re at it. Just $5/month. Upgrade
sight. Watch

About Help Legal

This is your last free story this month. Sign up and get an extra one for free.
https://itnext.io/how-to-migrate-from-vue-2-0-to-vue-3-0-composition-api-with-ts-part-2-replace-73606fb1b296 20/20

You might also like