How to Build Todo App using Vue Composition API and Vuex 4 with Typescript www.bacancytechnology.com
Quick Summary: Vue Composition API- Organized, Readable, and Understandable
Introduction
In this tutorial, we will learn and explore Vue Composition API. You might have heard about it, but if not then don’t worry at all! We will start from the basics. For knowing Vue Composition API in a better way you must have knowledge about Options API, we will discuss that too! I would suggest you visit my previous blog of the Vue 3 Tutorial series- How to Build To-do App with Vue 3 Typescript for setting up the basic demo project because in this tutorial we will be using the same github repository.
What is Vue Composition API?
Vue Composition API is function-based APIs that provides flexibility, improves code readability, and helps to maintain component logic. The main reason for introducing Vue Composition API was to address the limitations of Options API as the component gets larger. Here are some of the limitations associated with Options APIIneffective patterns for reusing logic and component Poor readability when component grows larger Code gets complex and difficult to manage when the project size increases Creates confusion and makes it difficult to use Typescript with ‘this
Vue Composition API vs Options API
You might have seen this image if you are learning Vue Composition API. Let’s see briefly what does it mean. The difference in the component because of Vue Composition API You will notice a setup() function is the major change. It comprises the component’s logic. In Options API we used to define data, methods, lifecycle, etc separately as a component option, but due to composition API, setup() function will consist of all these. You might not understand the impact of this update until your component size grows larger. If you worked with a large project having complex component code or have to understand other developers’ code, you might understand the significance of code understandability and readability
Vue Composition API sorts the component code and makes the logic reusable in a much better way
Let’s take a sample code from the Github repository: Vue 3 Typescript, which we have built in the previous blog- How to Build a To-do App with Typescript: Vue 3 Tutorial.
The One with Composition API export default defineComponent({ name: "Home", setup() { const tasks = ref([]); // ref is used to make the parameter reactive const store = useStore(); //alternative to Vue prototype of this.$store tasks.value = store.state.tasks; //this is the way to write methods const setTaskComplete = (task: Task): void => { store.commit(MutationType.CompleteTask, task); }; const deleteTask = (task: Task) => { store.commit(MutationType.DeleteTask, task); };
// To support two-way data binding return { tasks, setTaskComplete, deleteTask }; } }); </script>
On the contrary, you can see that the setup() function has combined all the six components together, which increases the readability and understandability of the code.
Steps: How to Build To-do App using Vue Composition API and Vuex 4 with Typescript.
Visit Vue 3 Tutorial with Typescript blog to create the vue-typescript project from scratch or click here to clone the vue-typescript-demo. For implementing Vue Composition API with Typescript follow the below steps.
1. Integrating Vuex 4 In the previous, files were written in Javascript with partial Typescript, but here we will update all the files with pure Typescript. For integrating Vuex 4 with Typescript, we will need to update two files: store/index.js and store/mutations.js.
store/index.js
Open store/index.js and update the file with the following code. import Task from "@/models/Task"; import { createStore, Store as VuexStore, CommitOptions } from "vuex"; import { Mutations, mutations } from "./mutations"; export const store = createStore({ state: { tasks: [ { name: "Demo for VueJS and TS", createdAt: new Date(), updatedAt: new Date(), completed: false, },
}, ] as Task[], }, mutations, actions: {}, modules: {}, }); //to make the store globally accessible export function useStore() { return store as Store; } export type Store = Omit<VuexStore<any>, "commit"> & { commit<K extends keyof Mutations, P extends Parameters<Mutations[K]>[1]>( key: K, payload: P, options?: CommitOptions ): ReturnType<Mutations[K]>; };
Explanation Use the createStore() method to create Vuex store. For using the store in different components export the useStore function. Thus, the complete store is accessible across our entire application. For accessing the store in the component, we need to inject it into the app. Thankfully, the Vue-CLI had already imported the entire store and passed it within the Vue instance of our application. Moving towards mutations.
store/mutation.ts Mutations are methods used for modifying the store state. Mutations accept the state as its first argument and payload as the second and then updates the state with the received payload. As per the recommendation by Vuex official doc, we will use constants for the mutation types. Open store/mutation.ts file and update it with the following code below.
import { MutationTree } from "vuex"; import { findIndex } from "lodash"; export enum MutationType { SetTask = "SET_TASKS", CompleteTask = "COMPLETE_TASK", DeleteTask = "REMOVE_TASK" } export type Mutations = { [MutationType.SetTask](state: any, task: any): void; [MutationType.CompleteTask](state: any, task: any): void; [MutationType.DeleteTask](state: any, task: any): void; };
export const mutations: MutationTree<any> & Mutations = { [MutationType.SetTask](state, task) { state.tasks.push(task); }, [MutationType.DeleteTask](state, task) { let taskIndex = findIndex(state.tasks, task); state.tasks.splice(taskIndex, ++taskIndex); }, [MutationType.CompleteTask](state: any, task: any) { const taskIndex = findIndex(state.tasks, task); state.tasks[taskIndex].completed = true; } };
Explanation Vuex package provides a generic typeMutationTree. It is used for declaring the type of mutation tree. MutationTypes enum stores all the possible names of mutations. Further, declaring a contract (types) for every MutationType. Create a variable named mutations for storing all the implemented mutations. The MutationTree < State > & Mutations ensures that the type is implemented correctly for avoiding Typescript errors.
2. Components using Composition API Implementing component API in the files – AddTask.vue and Home.vue. For that, you need to modify the code within < script > < script / > AddTask.vue <script lang="ts"> import { defineComponent, ref } from "vue"; import Task from "@/models/Task"; import { useStore } from "@/store"; import { MutationType } from "@/store/mutations"; import { useRouter } from "vue-router";
export default defineComponent({ name: "AddTask", setup() { const taskName = ref(""); const router = useRouter(); // Substitute of Vue prototype this.$router const store = useStore(); const addTask = (): void => { const newTask = new Task(taskName.value); store.commit(MutationType.SetTask, newTask); taskName.value = ""; router.push({ path: "/" }); }; return { taskName, addTask }; } }); </script>
What’s happening in this component? As the name suggests, it is used for adding new tasks to the to-do list. Whenever the user clicks the button Add Task, the addTask function commits the SetTask mutation which will add the newly added task to the existing tasks list. Once done, the UI is updated.
Home.vue <script lang="ts"> import { defineComponent, ref } from "vue"; import Task from "@/models/Task"; import { useStore } from "@/store"; import { MutationType } from "@/store/mutations";
export default defineComponent({ name: "Home", setup() { const tasks = ref([]); const store = useStore(); tasks.value = store.state.tasks; const setTaskComplete = (task: Task): void => { store.commit(MutationType.CompleteTask , task); }; const deleteTask = (task: Task) => { store.commit(MutationType.DeleteTask, task); }; </script>
return { tasks, setTaskComplete, deleteTask }; } }); What’s happening in this component? The component is responsible for displaying and updating (marking it done or deleting it) the to-do list. Whenever the user clicks the tick button, MutationType CompleteTask is triggered with an argument task, for marking the task as done. Whenever the user clicks the tick button, MutationType DeleteTask is triggered with an argument task, for deleting the task as done. Once done, the UI is updated.
Takeaway
● Integrate Vuex 4 with Typescript ● Implement Vue Composition API with Typescript
● Source code- Github Repository We have mostly used the major feature releases of Vuex 4 and integrated it with the Composition API in Vue 3 to develop a small demo app. With the practical implementation, we have explored the theoretical side of Composition API and seen how it is different than Options API.
I hope you’ve learned a great deal from the tutorial. If you have any suggestions or questions please feel free to comment below. Visit the VueJS Tutorials page for more such tutorials. If you are looking for skilled and experienced VueJS developers, contact Bacancy Technology to hire VueJs developers.
Thank You
www.bacancytechnology.com