← Other topics

Vue.js Simplified - The Basics (#2)

Series contents:

Video Notes

Introduction

In Part 1 of this series, we learned what Vue.js is and why you’d want to use it. Now let’s start with a simple example that will allow us to sample some of Vue’s key features. Later in this series, we‘ll dig deeper into each feature so consider this a broad introduction to start.

Example setup

To get started, follow these steps to set up our example:

  • Create a new directory on your computer called flashword
  • Within this directory create an empty JavaScript file named app.js
  • Also within this directory, create a HTML file named index.html with the following code:
<!doctype html>
<html lang='en'>

<head>
    <title>FlashWord</title>
    <meta charset='utf-8'>
    
    <script src='https://unpkg.com/vue@next' defer></script>
    <script src='app.js' defer></script>

    <style>
        label {
            display: block;
        }

        input,
        button {
            display: block;
            margin: 10px 0px;
        }

        .correct {
            color: green;
        }

        .incorrect {
            color: red;
        }
    </style>
</head>

<body>
    <h1>FlashWord</h1>

    <div id='app'>
        What is the English translation of the word <strong>{{ wordA }}</strong>?
    </div>
</body>

</html>

Open index.html in your browser and you should see the following:

Observations:

  • We’re importing Vue.js from http://unpkg.com, an external CDN (Content Delivery Network).
  • We’re using a development version - debug mode w/ full warnings, non-minified.
  • Later in this series, we’ll look at using a build system and NPM (Node Package Manager) to load Vue from within our own project.

New Vue instance

In app.js add the following code:

// Define the options of our application
const FlashWord = {
    data() {
        return {
            wordA: 'hola',
            wordB: 'hello',
            answer: '',
            correct: null,
            showFeedback: false,
        }
    }
}

// Create a new Vue instance using our options
const app = Vue.createApp(FlashWord).mount('#app');

Observations:

  • Our application can be designed using Vue options.
  • For example, the data option lets us pass an object of data to the Vue instance.
  • The data option must be a function that returns an object of data.
  • Our app instance is created using Vue.createApp and is “mounted” to the element on the page with the id app.
  • The template of our application is defined within that element.
  • Vue applications can be designed using the Options API (shown here) or the Composition API (covered later in this series).

Text interpolation

Data can be bound to the page via text interpolation using double curly bracket aka “mustache syntax”:

<div id='app'>
    What is the English translation of the word <strong>{{ wordA }}</strong>?
</div>

Reactive data

Data in our Vue app is all reactive — if it changes in one place, that change will propagate wherever else that data is being used.

To demonstrate this, we can update wordA via the web inspector console and see the change reflected where it’s printed on the page:

app.$data.wordA = 'adios'

All user-defined data is aliased, so you can also use the shorthand app.word when accessing it via the web inspector console.

Directives / v-model

Next, we want to set up a text input where the visitor can type in their answer. We’ll want this text input to be bound to our data option answer, and we’ll accomplish this using the Vue directive, v-model.

Add an HTML text input with the attribute v-model='answer', as well as a paragraph to output the answer:

<div id='app'>
    <label for='answer'>What is the English translation of <strong>{{ wordA }}</strong>?</label>

    <input type='text' id='answer' v-model='answer'>

    <p>
        Your answer: {{ answer }}
    </p>
</div>

v-model is our first example of a Vue directive.

Vue directives...

  • Are attributes you add to your HTML elements
  • Are prefixed with v-
  • Provide a way to reactively apply side effects to the DOM

The v-model directive...

  • Creates a two-way binding between a data property and a form input
  • Two-way binding means:
    • if the data property answer changes, so will the value of the text input
    • if the value of the text input changes, so will the answer data property

To observe the reactive binding, observe how when you change the value in the text input, the answer on the page is reactively updated.

Conditional rendering with v-if

Another useful directive is v-if which allows you to conditionally toggle the presence of an element on the page.

The v-if directive accepts a boolean expression; if that expression returns true, the corresponding element will be visible.

As an example, let’s make it so that the answer output only displays once the visitor has started to type an answer.

<p v-if='answer != ""'>
    Your answer: {{ answer }}
</p>

Other conditional-related directives include v-else, v-else-if, and v-show, which we’ll dig into more detail later in this series.

Directive arguments / Event listening with v-on

Some directives can take arguments which are added following a colon after the directive name. Here’s an example with the v-on directive, which is accepting the argument click:

<button v-on:click='doSomething'>Click me</button>

Other arguments for v-on include any native browser event as: click, change, mouseover, mouseout, keydown, etc.

To put an event listener to use, let’s add a Check Answer button after the answer input. This button will a) update the correct data property and b) toggle the showFeedback data property to true, which we’ll then use to render some feedback on the page.

<button v-on:click="correct = (answer == wordB); showFeedback = true">Check Answer</button>

Here’s some feedback output we can use:

<div v-if='showFeedback'>
    <p v-if='correct'>
        You got it!</p>
    <p v-else>
        Sorry, that is incorrect - try again.
    </p>
</div>

Methods

In the above example, our click listener executed the JavaScript expression correct = (answer == wordB); showFeedback = true. This works for simple one or two line expressions, but anything more complex than that would be better outsourced to methods, which is another option we can add to our Vue instance. To demonstrate, let’s create a checkAnswer method:

const FlashWord = {
    data() {
        return {
            wordA: 'hola',
            wordB: 'hello',
            answer: '',
            correct: null,
            showFeedback: false,
        }
    },
    methods: {
        checkAnswer() {
            // Note how data properties are accessed via `this`
            this.correct = this.answer == this.wordB; 
            this.showFeedback = true;
        }
    }
}

We’ll trigger this method from our button:

<button v-on:click="checkAnswer()">Check Answer</button>

Cloaking

You may observe that when your page is first rendered, in the split second before your JavaScript and Vue.js is loaded, all content in your HTML is displayed exactly as written:

Once the JavaScript is loaded and the Vue instance is created and bound to the DOM, the content of the page is rendered as expected.

That momentary “blip” of un-rendered content looks odd to the user. To avoid it, Vue uses a “cloaking” technique to hide the app before it’s ready.

To do this, add the v-cloak directive to your app:

<div id='app' v-cloak>
    [...]
</div>

Then, style this directive in your CSS so it’s invisible:

[v-cloak] {
    display: none
}

Once the Vue instance is compiled, the v-cloak directive will be removed, so the app will become visible.

Summary

  • When we initialize a Vue instance it’s mounted to an element on the page.
  • The Vue instance is configured via options such as data and methods.
  • One way data can be bound to the page is by using text interpolation using the mustache syntax {{ }}.
  • Vue directives appear in the form of a prefixed HTML attribute (v-); they’re used to apply side effects to elements.
  • Example directives include: v-model, v-if, v-else, v-else-if, v-on
  • Some Vue directives accept arguments (e.g. v-on:click)
  • The directive v-cloak can be used to hide unrendered Vue content seen on initial page load.
  • Vue instances can be designed using the Options API (shown in this example) or the Composition API (covered later in this series)

Practice

Add a reset button that appears once the user has guessed the correct answer. This button should reset the answer to a blank string and hide the feedback on the page.

Next...

Vue.js Simplified - Behind the Scenes (#3)

If this info helped you out, toss a coin in the tip jar?
← Other topics