Build A Word Counter with Vue.js

Please note that this post may contain affiliate links, and for every purchase you make, at no extra cost to you, a commission fee will be rewarded to me.

In this article, our focus is to investigate the lifecycle of Vue.js, while building a word counter. Again, let’s start by creating a new Vue component and registering it like we talked about in the previous article.

<template>

</template>

<script>
export default {
    name: "WordCounter"
}
</script>

<style scoped>

</style>
Vue.component('word-counter', require('./components/WordCounter.vue').default);

Vue Instance Lifecycle

When a Vue instance is created, it will go through a series of initialization steps. For example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes.

And during these steps, we are able to add our own code by using Vue lifecycle hooks. All lifecycle hooks are called with their this context pointing to the Vue instance invoking it.

In this tutorial, we’ll talk about four basic lifecycle hooks, created, mounted, updated and destroyed.

created

The created hook can be used to run code just after an instance is created. It allows you to perform actions before your component has been added to the DOM.

At this stage, the instance has finished processing the options which means you are able to access data and events that are active. However, the templates and virtual DOM have not been mounted or rendered.

Unlike other hooks, the created hook are involked during server-rendering.

mounted

mounted is the most often used lifecycle hook in Vue, it is called after the Vue instance has been mounted. You will have full access to data, events, templates, and rendered DOM.

Note that mounted does not guarantee that all child components have also been mounted. If you want to wait until the entire view has been rendered, you can use vm.$nextTick inside of mounted.

updated

Called after a data change causes the virtual DOM to be re-rendered and patched. The component’s DOM will have been updated when this hook is called, so you can perform DOM-dependent operations here. However, in most cases you should avoid changing state inside the hook.

The updated hook is usually used when you want to find out when your component re-renders, for debugging purposes.

destroyed

Called after a Vue instance has been destroyed. When this hook is called, all directives of the Vue instance have been unbound, all event listeners have been removed, and all child Vue instances have also been destroyed.

Since there is practically nothing left in your component by the time you reached the destroyed stage, the destroyed hook is usually used for some last minute clean up.

Lifecycle Diagram

These hooks that we talked about are all about after the instance has been created, mounted, updated, or destroyed. There are also hooks about before these stages for reached in your Vue instance lifecycle.

If you are interested, here is a list of all lifecycle hooks in Vue: https://vuejs.org/v2/api/#Options-Lifecycle-Hooks

Below is a lifecycle diagram from the Vue.js official website that might help you understand the lifecycle hooks and during which stage are they being involked.

This might be a little hard to understand for beginners, but don’t worry, let’s see one mounted lifecycle hook in action.

Building the Word Counter

HTML Template

This is the UI we’ll be using:

<template>
    <div class="word-counter">
        <div class="input-group my-3">
            <textarea v-model="input" class="form-control" aria-label="With textarea"></textarea>
        </div>
        <button type="button" class="btn btn-primary" v-on:click="count()"><i class="fas fa-play"></i> Count</button>
        <button type="button" class="btn btn-danger" v-on:click="clear()"><i class="far fa-window-close"></i> Clear
        </button>
        <div class="alert alert-primary my-3" role="alert" id="showWordCount">
            {{ wordCount }} words counted.
        </div>
    </div>
</template>

Line 4, the textarea element is binded with the input variable.

Line 6 and 7, when these two buttons are clicked, the count() or clear() methods are called.

JavaScript Code

<script>
export default {
    name: "WordCounter",
    data() {
        return {
            input: "",
            wordCount: "",
        }
    },
    methods: {
        count() {
            let count = 0;
            let text = this.input.split(' ');
            for (let i = 0; i < text.length; i++) {
                if (text[i] !== ' ') {
                    count++;
                }
            }
            this.wordCount = count;
        },
        clear() {
            this.input = "";
            this.wordCount = "";
        }
    }
}
</script>

The code is slightly more complicated than the unit converter that we built in the previous article. In the count() method, we split the input into an array of substrings.

For example, the string "How are you doing today?" will be split into the array {"How", "are", "you", "doing", "today?"}.

After that, we loop through all elements in the array, if the element is not ' ', the value of count increase by 1.

In the clear() method, all we need to do is just reset all variables back to null.

Now, we should have a fully functional word counter:

However, we still have a small problem, when the page is first loaded in your browser, the answer section (the blue part) will show even though there isn’t a value for wordCount, and that is not what we want.

To solve this problem, we add a mounted hook in our Vue instance.

Add mounted Hook

<script>
export default {
    name: "WordCounter",
    data() {
        return {
            input: "",
            wordCount: "",
        }
    },
    methods: {
        count() {
            let count = 0;
            let text = this.input.split(' ');
            for (let i = 0; i < text.length; i++) {
                if (text[i] !== ' ') {
                    count++;
                }
            }
            this.wordCount = count;
            document.getElementById("showWordCount").style.visibility = "visible";
        },
        clear() {
            this.input = "";
            this.wordCount = "";
            document.getElementById("showWordCount").style.visibility = "hidden";
        }
    },
    mounted() {
        document.getElementById("showWordCount").style.visibility = "hidden";
    }
}
</script>

In the mounted hook, the answer section, determined by the id "showWordCount", is set to be hidden. And in line 20, when the count() method is invoked, ie. when the Count button is clicked, the answer section is set to be visible.

Line 25, when the clear() method is called, the answer section is set back to hidden.

Finally, I have a question for you, do you think you can achieve the same purpose using the created hook instead? Try it out in your project, and comment on your findings below.

Leave a Reply

Your email address will not be published. Required fields are marked *