Vue.js Fundamentals: A Comprehensive Guide

For more advanced usage, refer to the official Vue.js documentation at https://vuejs.org/guide/extras/composition-api-faq.html

  1. Vue Instances

1.1. Creating Vue Instances

Every Vue application begins with creating a new Vue instance using the Vue constructor function:

const app = new Vue({
  // Configuration options
})

The constructor accepts an object containing various Vue configuration options, including:

  • el
  • data
  • methods

1.2. Templates and Elements

Each Vue instance needs to be associated with an HTML template for view rendering. This is specified using the el property:

<div id="app">
  <!-- Vue will render here -->
</div>

const vueApp = new Vue({
  el: "#app"
})

Vue will render based on the element with id "app". Features outside this element won't be accessible.

1.3. Data Handling

When a Vue instance is created, it automatically captures all properties defined in the data option for view rendering. Vue monitors these properties for changes, and when they occur, all related views are re-rendered. This is the "reactive" system.

<div id="app">
  <input type="text" v-model="username" />
</div>

const userApp = new Vue({
  el: "#app",
  data: {
    username: "alex"
  }
})

The username value affects the input field, and changes in the input update the username property in the Vue instance.

1.4. Methods

Vue instances can define methods that are accessible with in the Vue scope:

<div id="app">
  {{counter}}
  <button @click="increment">Increase</button>
</div>

const counterApp = new Vue({
  el: "#app",
  data: {
    counter: 0
  },
  methods: {
    increment() {
      this.counter++;
    },
    test() {
      this.counter++;
    }
  }
})

1.5. Lifecycle Hooks

1.5.1. Lifecycle

Each Vue instance goes through a series of initialization steps when created: instance creation, template loading, rendering, etc. Vue provides lifecycle hooks (listener functions) for each state.

1.5.2. Hook Functions

For example, the created hook is called after the Vue instance is created:

<div id="app">
  {{greeting}}
</div>

const vm = new Vue({
  el: "#app",
  data: {
    greeting: ''
  },
  created() {
    this.greeting = "Hello, World!";
  }
})

1.5.3. The 'this' Context

Let's examine what the 'this' variable represents inside Vue. We'll log it during the created hook:


<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue Test</title>
</head>
<body>
<div id="vue-test">
  <h1>Hello, {{name}}</h1>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>

<script>
  const testVue = new Vue({
    el: "#vue-test",
    data: {
      name: ""
    },
    created() {
      this.name = "hello, world";
      console.log(this);
    }
  });
</script>
</body>
</html>

  1. Directives

Directives are special attributes with a v- prefix. They expect a single JavaScript expression and their responsibility is to apply side effects to the DOM when the expression's value changes.

2.1. Interpolation Expressions

2.1.1. Mustache Syntax

Format:

{{ expression }}

Features:

  • Supports JavaScript syntax and can call built-in functions (must return a value)
  • Expressions must produce a result. For example, 1 + 1 is valid, but var a = 1 + 1; is not
  • Can directly access data or functions defined in the Vue instance

Example:

<div id="app">{{username}}</div>

const app = new Vue({
  el: "#app",
  data: {
    username: "John"
  }
})

2.1.2. Interpolation Flicker

Using {{}} can cause issues on slow networks. When data hasn't loaded, the page shows the original {{}} and only displays the correct data after loading. This is called interpolation flicker.

2.1.3. v-text and v-html

Use v-text and v-html directives as alternatives to {{}}:

  • v-text: Outputs data to element content. If the data contains HTML, it's treated as plain text
  • v-html: Outputs data to element content. If the data contains HTML, it's rendered
<div id="app">
  v-text: <span v-text="message"></span> <br/>
  v-html: <span v-html="message"></span>
</div>

const vm = new Vue({
  el: "#app",
  data: {
    message: "<h1>Hello, Summer!</h1>"
  }
})

This avoids interpolation flicker and shows blank content when no data is available.

2.2. v-model

v-model enables two-way binding between the view and model. While v-text and v-html provide one-way binding, v-model allows both directions.

v-model is limited to certain element types:

  • input
  • select
  • textarea
  • checkbox
  • radio
  • components

Example:

<div id="app">
  <input type="checkbox" v-model="languages" value="Java" />Java<br/>
  <input type="checkbox" v-model="languages" value="PHP" />PHP<br/>
  <input type="checkbox" v-model="languages" value="Swift" />Swift<br/>
  <h1>
    Selected: {{languages.join(',')}}
  </h1>
</div>

const vm = new Vue({
  el: "#app",
  data: {
    languages: []
  }
})

Key points:

  • Multiple checkboxes sharing a model result in an array type
  • Radio buttons correspond to the input's value
  • Input and textarea default to string type
  • Select single corresponds to string, multiple to array

2.3. v-on (shorthand: @click)

2.3.1. Basic Usage

v-on directive binds events to DOM elements:

<div id="app">
  <button v-on:click="counter++">Increase</button><br/>
  <button v-on:click="decrease">Decrease</button><br/>
  <h1>Counter: {{counter}}</h1>
</div>

const app = new Vue({
  el: "#app",
  data: {
    counter: 1
  },
  methods: {
    decrease() {
      this.counter--;
    }
  }
})

2.3.2. Event Modifiers

Vue provides event modifiers to handle common event requirements like preventing default actions or stopping propagation:

  • .stop: Stops event propagation
  • .prevent: Prevents default event behavior
  • .capture: Uses event capture mode
  • .self: Only triggers if the element itself is the target
  • .once: Executes only once

2.3.3. Key Modifiers

Vue allows adding key modifiers when listening to keyboard events:

<input v-on:keyup.13="submit">

<!-- Shorthand -->
<input @keyup.enter="submit">

Common key aliases:

  • .enter
  • .tab
  • .delete (captures both "delete" and "backspace")
  • .esc
  • .space
  • .up, .down, .left, .right

2.3.4. Modifier Combinations

Modifiers can be combined to trigger events only when specific keys are pressed:

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

2.4. v-for

v-for directive renders lists by iterating over data:

2.4.1. Iterating Arrays

Syntax:

v-for="item in items"

Example:

<div id="app">
  <ul>
    <li v-for="user in users">
      {{user.name}} : {{user.gender}} : {{user.age}}
    </li>
  </ul>
</div>

const app = new Vue({
  el: "#app",
  data: {
    users: [
      {name: 'Emma', gender: 'Female', age: 22},
      {name: 'Jack', gender: 'Male', age: 25},
      {name: 'Sophia', gender: 'Female', age: 28},
      {name: 'Lucas', gender: 'Male', age: 24},
      {name: 'Olivia', gender: 'Female', age: 26}
    ]
  }
})

2.4.2. Array Index

To access the array index during iteration, specify a second parameter:

v-for="(item, index) in items"

2.4.3. Iterating Objects

v-for can also iterate over objects:

v-for="value in object"
v-for="(value, key) in object"
v-for="(value, key, index) in object"

2.4.4. Key Attribute

When updating rendered element lists, Vue uses an "in-place patch" strategy. To help Vue track each node's identity and reuse elements efficiently, provide a unique key attribute:

<ul>
  <li v-for="(item, index) in items" :key="index"></li>
</ul>

2.5. v-if and v-show

2.5.1. Basic Usage

v-if conditional renders elements based on boolean expressions:

<div id="app">
  <button @click="isVisible = !isVisible">Toggle</button><br/>
  <h1 v-if="isVisible">
    Hello
  </h1>
</div>

const app = new Vue({
  el: "#app",
  data: {
    isVisible: true
  }
})

2.5.2. With v-for

When v-if and v-for appear together, v-for has higher priority. The list is iterated first, then conditions are evaluated.

2.5.3. v-else

The v-else directive represents an "else block" for v-if:

<div v-if="Math.random() > 0.5">
  Success!
</div>
<div v-else>
  Failure!
</div>

v-else must follow a v-if or v-else-if element.

2.5.4. v-show

v-show provides an alternative to conditionally display elements:

<h1 v-show="ok">Hello!</h1>

Difference: Elements with v-show are always rendered and remain in the DOM. v-show simply toggles the CSS display property.

2.6. v-bind

2.6.1. Binding Class Styles

To dynamically modify element attributes like class, use v-bind:

<div v-bind:class="isActive"></div> <!-- Shorthand: <div :class="isActive"></div> -->

Array syntax:

data: {
  isActive: ['active', 'hasError']
}

Object syntax:

<div v-bind:class="{ active: isActive }"></div>

2.6.2. Shorthend

v-bind:class can be shortened to :class

2.7. Computed Properties

Computed properties help simplify complex expressions in templates:

const app = new Vue({
  el: "#app",
  data: {
    birthdate: 1429032123201
  },
  computed: {
    formattedBirth() {
      const date = new Date(this.birthdate);
      return date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate();
    }
  }
})

Usage:

<div id="app">
  <h1>Your birthdate is: {{formattedBirth}}</h1>
</div>

2.8. Watchers

Watchers monitor value changes and react accordingly:

<div id="app">
  <input type="text" v-model="message">
</div>

const vm = new Vue({
  el: "#app",
  data: {
    message: ""
  },
  watch: {
    message(newVal, oldVal) {
      console.log(newVal, oldVal);
    }
  }
})

  1. Componentization

In large applications, pages can be divided into reusable components. This avoids duplication and improves maintainability.

3.1. Defining Global Components

Global components are defined using Vue.component:

<div id="app">
  <counter></counter>
</div>

Vue.component("counter", {
  template: '<button @click="count++">Clicked {{ count }} times</button>',
  data() {
    return {
      count: 0
    }
  }
})

const app = new Vue({
  el: "#app"
})

3.2. Component Reusability

Components can be reused multiple times independently:

<div id="app">
  <counter></counter>
  <counter></counter>
  <counter></counter>
</div>

Each component maintains its own state because data must be a function:

data: function() {
  return {
    count: 0
  }
}

3.3. Local Registration

For less frequently used components, local registration is preferred:

const counter = {
  template: '<button @click="count++">Clicked {{ count }} times</button>',
  data() {
    return {
      count: 0
    }
  }
};

const app = new Vue({
  el: "#app",
  components: {
    counter: counter
  }
})

3.4. Component Communication

3.4.1. Parent to Child: Props

Parent components can pass data to child components using props:

Vue.component("introduction", {
  template: '<h3>{{title}}</h3>',
  props: ['title']
})

const app = new Vue({
  el: "#app",
  components: {
    introduction: {
      template: '<h1>{{title}}</h1>',
      props: ['title']
    }
  }
})

3.4.2. Complex Data Passing

Components can receive complex data with type validation:

const itemList = {
  template: '\
    <ul>\
      <li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\
    </ul>\
  ',
  props: {
    items: {
      type: Array,
      default: []
    }
  }
}

3.4.3. Child to Parent Communication

Child components can communicate with parent components using events:

<div id="app">
  <h2>Counter: {{counter}}</h2>
  <counter :value="counter" @increment="increment" @decrement="decrement"></counter>
</div>

const counter = {
  template: '\
    <div>\
      <button @click="increase">+</button>  \
      <button @click="decrease">-</button>  \
    </div>',
  props: ['value'],
  methods: {
    increase() {
      this.$emit("increment");
    },
    decrease() {
      this.$emit("decrement");
    }
  }
}

const app = new Vue({
  el: "#app",
  data: {
    counter: 0
  },
  methods: {
    increment() {
      this.counter++;
    },
    decrement() {
      this.counter--;
    }
  },
  components: {
    counter: counter
  }
})

Tags: Vue.js frontend javascript reactive components

Posted on Fri, 24 Jul 2026 16:36:13 +0000 by plowter