DEV Community

Cover image for Create ToDo App With Vue 3 Composition API
Burak Gür
Burak Gür

Posted on

Create ToDo App With Vue 3 Composition API

Alt Text

Hi there,
I will show you how to create todo app with composition api. Composition api is new feature to Vue.js and it's like React Hooks.

Let's build app.

1. Create new Vue 3 project with Vue CLI.



vue create-app todo-app


Enter fullscreen mode Exit fullscreen mode

2. Create form and todo list in App.vue.



<template>
    <h1>ToDo App</h1>
    <form @submit.prevent="addTodo()">
        <label>New ToDo </label>
        <input
            v-model="newTodo"
            name="newTodo"
            autocomplete="off"
        >
        <button>Add ToDo</button>
    </form>
    <h2>ToDo List</h2>
    <ul>
        <li
            v-for="(todo, index) in todos"
            :key="index"
        >
            <span
                :class="{ done: todo.done }"
                @click="doneTodo(todo)"
            >{{ todo.content }}</span>
            <button @click="removeTodo(index)">Remove</button>
        </li>
    </ul>
    <h4 v-if="todos.length === 0">Empty list.</h4>
</template>


Enter fullscreen mode Exit fullscreen mode

3. Import ref package. Takes an inner value and returns a reactive and mutable ref object.



<script>
import { ref } from 'vue';
</script>


Enter fullscreen mode Exit fullscreen mode

4. The setup function is a new component option. Create setup function.



<script>
import { ref } from 'vue';
export default {
  name: 'App',
  setup () {
  }
}
</script>


Enter fullscreen mode Exit fullscreen mode

5. Create all property and methods. Also we use localStorage for data saving.



<script>
    import { ref } from 'vue';
    export default {
        name: 'App',
        setup () {
            const newTodo = ref('');
            const defaultData = [{
                done: false,
                content: 'Write a blog post'
            }]
            const todosData = JSON.parse(localStorage.getItem('todos')) || defaultData;
            const todos = ref(todosData);
            function addTodo () {
                if (newTodo.value) {
                    todos.value.push({
                        done: false,
                        content: newTodo.value
                    });
                    newTodo.value = '';
                }
                saveData();
            }
            function doneTodo (todo) {
                todo.done = !todo.done
                saveData();
            }
            function removeTodo (index) {
                todos.value.splice(index, 1);
                saveData();
            }
            function saveData () {
                const storageData = JSON.stringify(todos.value);
                localStorage.setItem('todos', storageData);
            }
            return {
                todos,
                newTodo,
                addTodo,
                doneTodo,
                removeTodo,
                saveData
            }
        }
    }
</script>


Enter fullscreen mode Exit fullscreen mode

That's it. Also i add some SCSS code in App.vue. See demo:

Demo: https://todo-app.burakgur.vercel.app/

Repo: https://github.com/BurakGur/vue3-composition-api-todo-app

Thanks for reading 😊

Top comments (8)

Collapse
 
chandragie profile image
chandragie • Edited

I haven't touched Vue 3 yet so far, that make me curious, is it the composition API or that ref package which enable you not declaring data:function(){ ... } instead just use it directly under setup() function? I don't see newTodo is declared here yet you use it as v-model.

Collapse
 
burakgur profile image
Burak Gür

Normally, we use options api with vue 2. Options api included data, mounted, created etc. functions. On the other hand, composition api is included setup function. And then setup function is included onMounted, onBeforeMount, custom methods, ref definitions, etc. We cannot use ref outside of the setup function.

Collapse
 
chandragie profile image
chandragie

Thanks for explaining! Gonna learn Vue 3 soon!

Collapse
 
singhtanya123 profile image
Winter-leaf

Hey , JSON.parse(localStorage.getItem('todos'))
This code doesn't have any todos, from where it is saving and fetching data.

Collapse
 
rodrigosantosdev profile image
Rodrigo Santos

move the page scroll, there's more content to the side #bug

Collapse
 
rodrigosantosdev profile image
Rodrigo Santos

const todosData = JSON.parse(localStorage.getItem('todos')) || defaultData;

Collapse
 
madza profile image
Madza

nice and clean looking

Collapse
 
ni4yja profile image
Liuba Kuibida

Thank you for this post. It inpired me to write this article ni4yja.medium.com/how-to-filter-to...