Getting Started with Vuex: Managing State in Vue.js

Getting Started with Vuex: Managing State in Vue.js

In this tutorial, we will be diving into Vuex by building a nice todo app.

Table of Contents

  1. State Management
  2. Setting up Vue and Vuex
  3. Vuex Overview
  4. Vuex State
  5. Vuex Getters
  6. Vuex Mutations
  7. Vuex Actions
  8. Vuex Store
  9. Building our Vue Components
  10. The Markup and Styles
  11. Conclusion

Breaking down larger pieces of an app into smaller components has become really popular thanks to the rise of front-end libraries like React and Vue. Components allow you to easily reuse code, reduce architectural complexity, and build impressive user interfaces by logically dividing your code into independent chunks.

However, despite these advantages, one issue that eventually hits any application that grows large enough is the difficulty of managing its state. Facebook's answer to this challenge was Flux, a pattern that later served as the basis for the more popular Redux state management library that is commonly used with React.

The Vue team, realizing that their library would also need a way to manage state, introduced Vuex, the official state management library for Vue.

In this tutorial, we will be diving into Vuex by building a nice todo app. Make sure that you are comfortable with both JavaScript and Vue before continuing with this tutorial. This is what we will be building:

The todo list app we'll be building.

You can check out a live demo of the finished app here.

State Management

As mentioned before, state management becomes tricky when your app becomes larger and more complex. You can get away without standalone state management if your app is small, but as it grows, your code could easily become a nightmare to debug and iterate upon.

The state of an application is a collection of variables and their values at that point in time (basically the data powering your app). For example, if you open a calculator app for the first time, its current total would be 0 so its state could look like this:

	
    {
        total: 0
    }
	

After you evaluate 2 + 4, its state could look like this:

	
    {
        total: 6
    }
	

This is where Vuex comes into play. It offers you a clear and organized way to initialize, manage, and modify your Vue application's state in a straightforward and easy-to-track way.

Setting up Vue and Vuex

Create a folder to serve as the root directory for this app, and create three files in that folder, index.html to contain our markup, styles.css for our styles, and app.js for our code.

Put this inside your index.html:

	
    <html>
        <head>
            <title>Todo List</title>
            <link rel="stylesheet" href="styles.css">
        </head>
        <body>
            <div class="container">
                <h1>Todo List</h1>
                <div id="app"></div>
            </div>
            <script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
            <script src="https://unpkg.com/[email protected]/dist/vuex.min.js"></script>
            <script src="app.js"></script>
        </body>
    </html>
	

This pulls in our styles from styles.css and imports the following three JavaScript files:

  1. Vue from the Unpkg CDN
  2. Vuex from the Unpkg CDN
  3. Our app.js script in our folder

At this point, your project folder should look like this:

Your project folder.

Vuex Overview

The whole idea behind Vuex is confusing at first but becomes clear with time. A simple overview of Vuex and its most important concepts are critical to be familiar with as it will make building this app (and future ones) much easier.

In Vuex, you have something called the store. The store is a global object that contains four major things that Vuex needs to manage state in our Vue app. We'll go over each four below.

The first thing our store needs is the state. This is Vuex's bread and butter. The state is the JavaScript object that contains the actual data that your app needs to function.

We can retrieve data from the store by defining the getters of the store and then calling them when we need to. The getters are just functions that get the data from the state for you.

Now that we can get data from the state, we need a way to change or modify it. For example, when a new calculation is evaluated on a calculator, you'd want the total to be updated. This changing of the state is called mutating it. Thus, changes to the state are also called mutations.

One final thing to keep in mind is that even though mutations are what actually modify the state, the functions should not be called directly. Mutations to the state should only be called by separate functions called actions.

The idea here is that while you technically can just directly mutate the state to your liking, action functions that themselves call mutations ensure we can modify our state in a predictable, safe, and clean way.

So, to recap, here are the four major concepts of a Vuex store:

  1. State: The object that holds your app's data.
  2. Getters: Functions that return back data contained in the state.
  3. Mutations: Functions that directly mutate the state, as the state is an immutable object.
  4. Actions: Functions that call mutations on the state. They can call multiple mutations, can call other actions, and they support asynchronous operations.

Here is a diagram of Vuex which should hopefully make more clear what is going on:

A diagram of Vuex from the official project Github page.

Users will interact with the Vue components on their screen. Some of these interactions will trigger action functions that then commit mutations on the state. After the state has been mutated, Vue uses this new state to re-render the affected components on the screen.

Now, let's get to some implementing!

Vuex State

The first step in using Vuex is simply deciding on what pieces of data your app will need to function properly, the state. Recall that we are building a todo list app. With that in mind, it is logical to conclude that in our simple example we will only need a single thing to hold in our state, the array of todo items.

Each todo item should contain a string that describes the task and then a boolean to keep track of whether or not the item was completed. Also, to keep track of our items, we'll give them each a unique ID number.

Here is the state of our Vue app, initialized with three example todo items.

	
    var state = {
        todos: [
            {
                id: 0,
                task: "Buy food at the supermarket.",
                completed: false
            },
            {
                id: 1,
                task: "Organize the living room.",
                completed: true
            },
            {
                id: 2,
                task: "Read every class and tutorial on Sabe.io.",
                completed: false
            }
        ]
    };
	

Vuex Getters

Luckily for us, in this example, our state only contains a single thing, the array of our todo items. Because of this simplicity, we only need a single getter function that retrieves the entire array.

	
    var getters = {
        getTodos: state => state.todos
    };
	

The getTodos() function takes the state object that we defined (and that Vuex passed in automatically for us), and simply returns the todos array for us.

Onwards to mutations!

Vuex Mutations

Recall that the only job of mutation functions is to mutate, or modify, the state. In our example, there are three things we would ever need to do to our state:

  1. Add a new item: When we want a new todo item, we should be able to add it to the array.
  2. Toggle the completion: We should be able to go back and forth between the two completion states of a task.
  3. Delete an item: When we no longer want a todo item, we should be able to remove it from the array.

Keeping this in mind, here are our three mutations:

	
    var mutations = {
        ADD_TODO: (state, payload) => {

            var newTask = {
                id: payload.newId,
                task: payload.task,
                completed: false
            }

            state.todos.unshift(newTask);
        },
        TOGGLE_TODO: (state, payload) => {
            var item = state.todos.find(todo => todo.id === payload);
            item.completed = !item.completed;
        },
        DELETE_TODO: (state, payload) => {
            var index = state.todos.findIndex(todo => todo.id === payload);
            state.todos.splice(index, 1);
        }
    };
	

Per convention, mutation functions are capitalized to distinguish them from other functions.

Mutation functions, in addition to getting access to the state, also get access to a payload, which is just the information needed to make the mutation. In the case of ADD_TODO the payload is all the information needed to create a brand new todo item, and in the case of TOGGLE_TODO and DELETE_TODO, we only care about the ID of the todo item, so we only passed that in.

Ultimately in all three mutation functions, we are just doing basic array manipulation:

  1. In ADD_TODO, we are simply creating a brand new item and adding it to the array via unshift.
  2. In TOGGLE_TODO, we are finding the todo item in the array via its unique ID, then inverting its completed boolean.
  3. In DELETE_TODO, we are finding the todo item in the array and then removing it via splice.
Vuex Actions

The final piece of the puzzle is our action functions. Again, recall that these functions exist to call mutator functions. They're going to be straightforward in this case, but in more complex apps, they are used to perform asynchronous actions and evaluate some logic before making the actual mutations on the state.

Because we don't need to do much here, our action functions are going to be extremely simple.

	
    var actions = {
        addTodo: (context, payload) => {
            context.commit("ADD_TODO", payload)
        },
        toggleTodo: (context, payload) => {
            context.commit("TOGGLE_TODO", payload)
        },
        deleteTodo: (context, payload) => {
            context.commit("DELETE_TODO", payload)
        }
    }
	

Don't let terms confuse you, context is just the store and commit is just the function name that calls a mutation function with the provided payload.

The first parameter of the commit function is the name of the mutation, then the second parameter is the payload needed to make that mutation. In our case, we just pass along the payload given to our action functions.

Vuex Store

At last, we have all four pieces and can finally put it all together to have a working Vuex store for our app. Now all we need to do is define a new store and pass everything we just defined in:

	
    var store = new Vuex.Store({
        state: state,
        getters: getters,
        mutations: mutations,
        actions: actions
    });
	

We are now completely ready to start incorporating the use of our store inside our Vue app, so let's start on that!

Building our Vue Components

Believe it or not but with our store fully defined and ready to go, we have already built the majority of this app. The rest from this point on is just building the user interface for it.

Ideally for our app we are going to want two components, the component that contains the list of todo items, and then the overall component that contains the entire app, including the form that you use to create new todo items.

Todo Items List Component

We'll start with the todo items list component:

	
    Vue.component("todo-list", {
        computed: {
            todos() {
                return this.$store.getters.getTodos;
            }
        },
        methods: {
            toggleTodo: function(id) {
                this.$store.dispatch("toggleTodo", id);
            },
            deleteTodo: function(id) {
                this.$store.dispatch("deleteTodo", id);
            }
        },
        template: "#todo-list"
    });
	

For the list to render properly, it needs the todo items from the store, and so we'll make it accessible via a computed property that returns it from the store. Since the parent is taking care of adding, we only need to support toggling and deleting, and thus we have the two methods toggleTodo and deleteTodo.

If you've noticed, both of these methods just do one thing: dispatches an action. They pass in the ID of the todo item being affected as the payload to be used by the action function (and later the mutator function).

Finally, we set the template to #todo-list so that Vue knows where to get the markup to use for this component.

Todo Parent Container Component

With the list component ready to go, the last part left is defining the Vue app itself that will serve as the glue that holds everything together, and here it is:

	
    var app = new Vue({
        data: () => ({
            task: "",
            newId: 3
        }),
        methods: {
            addTodo: function() {
                this.$store.dispatch("addTodo", this);
                this.newId ++;
                this.task = "";
            }
        },
        store: store,
        el: "#app",
        template: "#app-template"
    });
	

The data function initializes the task string to being empty so that the user is free to create a brand new task, and newId is set to 3 because we already have three items and want every todo item to have a unique ID. If you initialize the app with more or less todo items, you will have to adjust this variable's initial value.

Under methods, we define the addTodo function which dispatches the addTodo action, passing in this as the payload (which includes the current value for task and the id of the new task item). After the action is dispatched, we increment the newId property so that the next task's ID is ready to go, and reset the value of the task string.

Finally, we pass in the store we defined to Vue, the element we want Vue to mount on, #app, and then the template we want to use, #app-template.

The Markup and Styles

With all the JavaScript in place, it's time to go back and bring our index.html and styles.css files up to speed. Since we defined two new templates for our Vue components, #todo-list and #app-template, we must provide them to Vue.

Add this to your index.html directly above your JavaScript script tags.

	
    <template id="todo-list">
        <ul class="tasks">
            <li v-for="todo in todos"
                :class="{completed: todo.completed}"
                class="task"
                @click="toggleTodo(todo.id)"
                @dblclick="deleteTodo(todo.id)">{{todo.task}}</li>
        </ul>
    </template>
    <template id="app-template">
        <div>
            <form @submit.prevent="addTodo">
                <input class="todo-input" type="text" placeholder="Enter a new Task" v-model="task" />
            </form>
            <todo-list />
        </div>
    </template>
	

At this point, your app should technically work completely and offer these features:

  1. Type a new task and press enter to add it to the list.
  2. Click on a task to toggle its completion status.
  3. Double-click on a task to remove it completely.

However, we want to make our todo list app look pretty. 😍 Open your styles.css and add this:

	
    html {
        font-family: sans-serif;
        background: linear-gradient(45deg, #6cfd9f, #6887ff);
        height: 100%;
        color: #333;
    }
    body {
        display: flex;
        height: 100%;
        margin: 0;
    }
    .container {
        width: 24rem;
        margin: auto;
        background-color: white;
        border-radius: 0.5rem;
        padding: 1rem;
        box-shadow: 0 0 2rem rgba(0, 0, 0, 0.25);
    }
    h1 {
        text-align: center;
        margin-top: 0;
    }
    .todo-input {
        width: 100%;
        padding: 0.5rem;
        font-size: 1rem;
        outline: none;
        border-radius: 0.25rem;
        border-style: none;
        border: solid 1px lightgray;
        box-sizing: border-box;
    }
    .tasks {
        padding-left: 1.5rem;
    }
    .task {
        margin-bottom: 0.5rem;
    }
    .task:hover {
        cursor: pointer;
    }
    .completed {
        text-decoration: line-through;
        color: #555;
    }
	

Conclusion

Your app is now ready to go. Open index.html and see the power of Vuex right before your very eyes.

The todo list app you built.

Again, you can check out a live demo here.

Recall that when you do stuff like add a new todo item, invert its completion boolean, or delete it, here is what is actually happening under the hood:

  1. You first do something.
  2. This triggers an action and a payload is passed in.
  3. Actions then call mutations on the state, and pass in a payload.
  4. Mutation functions alter the state with that payload.
  5. Vue automatically re-renders what it needs to re-render given this new state.

I hope that this example app has illustrated just how powerful Vuex can be. On a much bigger application, having standalone state management with Vuex would be crucial for clean code.

What are the differences between the various JavaScript frameworks? E.g. Vue.js, Angular.js, React.js

What are the differences? Do they each have specific use contexts?

What are the differences? Do they each have specific use contexts?

Ember.js vs Vue.js - Which is JavaScript Framework Works Better for You

Ember.js vs Vue.js - Which is JavaScript Framework Works Better for You

In this article we will discuss full details and comparison of both Ember.js and Vue.js

JavaScript was initially created to work for web applications. But today they have become the favorite of mobile app developers. Most of the developers prefer to work with frameworks based on JavaScript. It simplifies coding. You can use JavaScript with almost any framework.

The use of a particular framework will decide how easy and fast it is to create the app. So, you must choose the best one suited for the app that you are planning to build. You must make a wise choice so that you benefit in the end. Among the crowded market, two of the frameworks stand out. We will make a comparison between Ember.js and Vue.js.

Why Do You Select A Particular Framework?

Before we start comparing the two frameworks, we should understand the factors that lead to the choice of a framework. Each developer chooses a framework before he or she goes to work on an app. Let us see the reasons for the selection.

● The codes must be easy to understand and transparent.

● The framework should give the maximum power with the least amount of coding.

● The framework should provide a well laid out structure to work on.

● Does the framework support an in-built router or an external plug-in router?

● The framework should be able to transfer more data on a full page-load so that it becomes a single-page app. A single-page app is more beneficial for the application.

● In single page architectures if there is a need for users to share links to sub-screens within the interface, then the framework should have the capacity to route based on the URL.

● A tighter template option can help in enabling two-way binding.

● The framework should not conflict any third-party library.

● Testing the codes inside the framework should be easy.

● The framework should provide the HTTP client service for AJAX calls

● The documentation is essential. It should be complete and up-to-date.

● The framework should be compatible with the latest version of the browser.

● The framework has to fulfill the above conditions for easy construction of the app. You must ensure that the framework you choose meets the conditions.

Vue.js Explained

Developers are always looking at new frameworks to build their apps. The main requirements are speed and low cost. The framework should be easy to use by even new developers. You should be able to use it at low cost. Other considerations are about simple coding, proper documentation, etc.

Vue.js combines a lot of good when it comes to software language for web app development. The architecture of Vue.js is easy to put in use. The apps developed using Vue.js are easy to integrate with new apps.

Vue.js is a very lightweight framework. It makes it fast to download. It is also much faster than other frameworks. The single-file component nature of the framework is also beneficial. The size has made it very popular.

You can further decrease weight. With Vue.js you can separate the template-to-virtual DOM and compiler. You can only deploy the minified and zipped interpreter which is only 12 KB. You can compile the templates in your machine.

Another significant advantage of Vue.js is that it can integrate easily with existing applications created with JavaScript. It will make it easy for using this framework to make changes to applications already present.

Vue.js also integrates easily with other front-end libraries. You can plug in another library and make up for any deficiency in this framework. This feature makes this tool a versatile one.

Vue.js uses the method of rendering on the streaming-side server. You can render your component and get a readable stream. You can then send this to the HTTP server. It makes the server highly responsive. Your users will get the rendered content very quickly.

Vue.js is very SEO friendly. As the framework supports server-side rendering, the views are rendered directly on the server. The search engines list these.

But the most important thing for you is the ease with which you can learn Vue.js. The structure is elementary. Even new developers will find it easy to use it to build their apps. This framework helps in developing both small and large templates. It helps to save a lot of time.

You can go back and check your errors very easily. You can travel back and inspect all the states apart from testing your components. It is another important feature as far as any developer is concerned.

Vue.js also has very detailed documentation. It helps in writing your applications very quickly. You can build a web page or app with the basic knowledge of HTML or JavaScript.

● Vue.js has pure architecture. It helps in integration with other apps

● Vue.js is lightweight and fast. It can be made lighter by deploying only the interpreter

● You can separate the compiler and the template-to-virtual DOM.

● Due to smooth integration, you can use this to make changes to existing apps

● To make up for any shortfall, you can plug-in any library and makeup.

● As Vue.js uses streaming-side server rendering, your users can get quick responses.

● The server-side rendering also helps in being ranked higher by search engines.

● It has a simple structure. Easy to use for any new developer

● You can go back and check and correct your errors.

● You can check all the existing states.

● Detail documentation also helps build the web page or application very quickly.

Ember.js Decoded

Ember.js is an MVVM model framework. It is open-source software. This platform is mostly used for creating complex multi-page applications. It maintains up-to-date features without discarding any of the old features.

With this framework, you have to follow the architecture of the framework strictly. The JS framework is very tightly organized. It reduces the flexibility that other frameworks might offer.

There is a very refined and developed control system for its platforms and tools. You can integrate it with the new version with the tools provided. There is strict guidance about avoiding outdated APIs.

You can understand Ember’s APIs easily. They are also easy to work. You can make use of highly complex functionalities simply and straightforwardly.

The performance is better as similar jobs are processed together. It creates batches of similar bindings and DOM updates to improve the performance. It means that the browser needs to process them in one go. It will avoid recomputing for each task, wasting a lot of time.

You can write the codes in a simple manner and modules. You can use any of Ember’s APIs. It is possible due to the presence of Promises everywhere.

Ember comes with a well-written guide. The API is recorded in a useful manner. It is a front-end framework that is loaded. Ember has a router, pipeline, services, etc. of its own.

The basis for views, controllers, models, and framework is the Ember Object Model. All components come from the same objects. The framework is firm and steady. The reason is that all elements have similar jobs and characteristics.

Ember has made the general application, organization, and structure clear so that you don’t make any mistakes. You will have no chance to complicate the application unnecessarily. If you have to go out of the defined limits, you will have to force your way out.

The language used for templating in Embers is Handlebars. This language helps Embers to keep its logic out of view. The clean syntax of Handlebars makes it easy for you to read and understand the templates. Handlebar templates are faster to load.

Another advantage you gain from Handlebar is that you don’t have to update your template every time you add or remove data from the page. It will be done automatically by the language itself.

A community that is continually improving the framework supports Ember. They are updating the framework with the latest technology. They also make sure that backward compatibility is possible.

● Ember.js is an open-source MVVM model framework suitable for complex multiple-page applications.

● It offers both the latest and old features.

● It has a very tightly structured framework which doesn’t offer much flexibility

● A very refined control system helps you to integrate with new versions without any problem.

● There is strict guidance about avoiding outdated API versions.

● Ember’s APIs help you to use complex functionalities in a simple manner

● There is no recomputing for each task as the framework allows the browser to do similar functions together.

● Promises allow you to write modular and straightforward code using any API of Ember.js.

● Ember.js is a fully loaded, front-end framework.

● The framework is stable because all components have the same functionalities and properties.

● It has well-defined limitations which will prevent your complicating your application

● Handlebars, the language used by Ember.js allows you to read and understand templates easily. It also helps to load the templates faster.

● Handlebars will ensure to update the template every time you add or remove data.

● Ember.js has an active community that updates the framework regularly and facilitates backward compatibility.

A Comparison Between Ember.js And Vue.js

This article intends to compare the features of both frameworks. Let us see how the characteristics of these frameworks compare. It will help you to make use of the right framework for your web application.

When you need a modern engine for an old application, it is Vue.js which will help you. It combines the best properties of other frameworks. Vue.js is a developing framework. A ready-to-use library of interface elements does not exist. However, many third-party libraries can help you.

Ember.js offers you a well-organized and trustworthy framework. When the development team is big, this is the framework that suits best. It allows everyone to understand the written code and contribute to a common project. The technology will be up-to-date, and the platform will be stable.

Vue.js can help you use the syntax of different kinds. It helps in writing the codes with ease. It is also an SEO friendly framework. Ember is a fully loaded front-end framework and can help you develop the applications very fast. But it is not suitable for developing small projects.

It is not easy to say this is better than that. It will depend on what kind of project you have undertaken. Both have their pluses and minuses. The below table will help in a better comparison.

Final Thoughts

It is not easy to conclude as to which is better. It all depends on the application that you want to develop. Both frameworks are developing. Both are getting updates. Both the communities are working on the frameworks.

While Vue.js is more comfortable for writing codes, Ember is a full-stack framework allowing the development of apps very fast. It is suitable for big projects. It is too complicated to be used for smaller projects.

We hope you had a great time reading this article. If you’ve any questions or suggestions related to this blog, then feel free to ask them in the comment section. Thank You.!