Vue.js Instance
Introduction
At the heart of every Vue.js application lies the Vue instance. This is the starting point of Vue applications and serves as the root of your component tree. Understanding the Vue instance is fundamental to mastering Vue.js as it controls the entire application and manages how data flows through your components.
In this lesson, we'll dive into what a Vue instance is, how to create one, its properties and methods, and understand its lifecycle. By the end, you'll have a solid grasp of the Vue instance and how it powers your applications.
Creating a Vue Instance
Every Vue application starts by creating a new Vue instance with the Vue
constructor:
const app = Vue.createApp({
// options here
});
// Mount the app to a DOM element
app.mount('#app');
For Vue 2, the syntax is slightly different:
const vm = new Vue({
// options here
});
// Mount the instance to a DOM element
vm.$mount('#app');
In Vue 3 (the current version), we use createApp()
to create the application instance. This is the main entry point that we use to interact with Vue's features.
The Root Component
When you create a Vue instance, you pass an options object that contains the configuration for your app:
const app = Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
},
methods: {
reverseMessage() {
this.message = this.message.split('').reverse().join('')
}
}
});
app.mount('#app');
This creates a Vue application and mounts it to the element with the id app
in your HTML:
<div id="app">
<p>{{ message }}</p>
<button @click="reverseMessage">Reverse Message</button>
</div>
When this code runs, Vue will render the message in the paragraph and set up the click event on the button to reverse the message text when clicked.
Vue Instance Properties and Methods
When you create a Vue instance, it adds several properties and methods to help you build your application. Let's explore some of the most important ones:
Data Properties
The data
property is a function that returns an object containing all the reactive data properties your component needs:
const app = Vue.createApp({
data() {
return {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
});
Vue makes these data properties reactive, meaning when they change, the view updates automatically.
Methods
Methods are functions that you can use in your Vue instance:
const app = Vue.createApp({
data() {
return {
counter: 0
}
},
methods: {
increment() {
this.counter++
},
decrement() {
this.counter--
},
greet(name) {
return `Hello, ${name}!`
}
}
});
You can call these methods from templates:
<div id="app">
<p>Counter: {{ counter }}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<p>{{ greet('Vue Developer') }}</p>
</div>
Computed Properties
Computed properties are like methods, but they are cached based on their dependencies:
const app = Vue.createApp({
data() {
return {
firstName: 'John',
lastName: 'Doe'
}
},
computed: {
fullName() {
return `${this.firstName} ${this.lastName}`
}
}
});
Usage in template:
<div id="app">
<p>Full name: {{ fullName }}</p>
</div>
Computed properties only re-evaluate when their dependencies change, making them more efficient than methods for properties that need to be derived from other data.
Watchers
Watchers let you react to data changes:
const app = Vue.createApp({
data() {
return {
question: '',
answer: 'Questions usually contain a question mark. ;-)'
}
},
watch: {
// whenever question changes, this function will run
question(newQuestion, oldQuestion) {
if (newQuestion.includes('?')) {
this.getAnswer()
}
}
},
methods: {
getAnswer() {
this.answer = 'Thinking...'
setTimeout(() => {
this.answer = 'I need more information to answer that!'
}, 1000)
}
}
});
The Vue Instance Lifecycle
Every Vue instance goes through a series of steps when it's created—this is called the lifecycle. During these steps, Vue calls specific functions known as lifecycle hooks, which give you the opportunity to add your own code at specific times.
Here's a diagram of the Vue instance lifecycle:
Let's look at the most commonly used lifecycle hooks:
1. beforeCreate
Called immediately after the instance is initialized, before data observation and event/watcher setup.
2. created
Called after the instance has finished processing all data observation, computed properties, methods, and event callbacks. At this stage, the instance has become reactive, but the DOM hasn't been mounted yet.
3. beforeMount
Called right before the mounting begins: the render
function is about to be called for the first time.
4. mounted
Called after the instance has been mounted, where the element is replaced by the newly created DOM element. This is a good place to access the DOM or integrate with third-party libraries.
5. beforeUpdate
Called when data changes, before the DOM is patched.
6. updated
Called after a data change causes the virtual DOM to be re-rendered and patched.
7. beforeUnmount
Called right before a Vue instance is unmounted.
8. unmounted
Called after a Vue instance has been unmounted, when all directives are unbound and event listeners are removed.
Here's an example using some lifecycle hooks:
const app = Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
},
created() {
console.log('Instance created!', this.message)
},
mounted() {
console.log('Instance mounted!')
},
updated() {
console.log('Instance updated!')
},
unmounted() {
console.log('Instance unmounted!')
}
});
app.mount('#app');
Practical Example: Todo List
Let's build a simple todo list application to demonstrate the Vue instance in action:
<div id="todo-app">
<h1>My Todo List</h1>
<input
v-model="newTodo"
@keyup.enter="addTodo"
placeholder="Add a new task"
/>
<ul>
<li v-for="(todo, index) in todos" :key="index">
<input type="checkbox" v-model="todo.completed">
<span :class="{ completed: todo.completed }">{{ todo.text }}</span>
<button @click="removeTodo(index)">Delete</button>
</li>
</ul>
<div v-if="todos.length > 0">
<p>{{ remainingTodos }} tasks remaining</p>
<button @click="clearCompleted">Clear completed</button>
</div>
</div>
const app = Vue.createApp({
data() {
return {
newTodo: '',
todos: [
{ text: 'Learn Vue.js', completed: false },
{ text: 'Build a Vue app', completed: false },
{ text: 'Share with friends', completed: false }
]
}
},
computed: {
remainingTodos() {
return this.todos.filter(todo => !todo.completed).length
}
},
methods: {
addTodo() {
if (this.newTodo.trim()) {
this.todos.push({
text: this.newTodo.trim(),
completed: false
})
this.newTodo = ''
}
},
removeTodo(index) {
this.todos.splice(index, 1)
},
clearCompleted() {
this.todos = this.todos.filter(todo => !todo.completed)
}
},
mounted() {
// Focus the input when the component mounts
document.querySelector('input').focus()
}
});
app.mount('#todo-app');
Add some CSS to make it look better:
<style>
.completed {
text-decoration: line-through;
color: #999;
}
li {
margin: 8px 0;
}
button {
margin-left: 10px;
}
</style>
This example demonstrates many Vue instance features:
- Data properties with reactive todos
- Computed property for remaining tasks
- Methods for adding, removing, and clearing todos
- Lifecycle hook (
mounted
) to focus the input field - Reactive data binding with
v-model
Example: Using Multiple Instances
In complex applications, you might have multiple Vue instances working together:
<div id="app-1">
<h2>App 1: {{ message }}</h2>
<button @click="changeMessage">Change Message</button>
</div>
<div id="app-2">
<h2>App 2: {{ message }}</h2>
<button @click="changeMessage">Change Message</button>
</div>
// First Vue instance
const app1 = Vue.createApp({
data() {
return {
message: 'Hello from App 1!'
}
},
methods: {
changeMessage() {
this.message = 'App 1 message has been updated!'
}
}
}).mount('#app-1');
// Second Vue instance
const app2 = Vue.createApp({
data() {
return {
message: 'Hello from App 2!'
}
},
methods: {
changeMessage() {
this.message = 'App 2 message has been updated!'
}
}
}).mount('#app-2');
In this example, we have two separate Vue instances, each with its own scope. Changes in one app won't affect the other.
The Vue Instance and Components
While the root Vue instance is important, most Vue applications consist of multiple components that extend the base Vue functionality:
// Define a component
app.component('todo-item', {
props: ['todo'],
template: `
<li>
<input type="checkbox" v-model="todo.completed">
<span :class="{ completed: todo.completed }">{{ todo.text }}</span>
<button @click="$emit('delete')">Delete</button>
</li>
`
});
// Use it in the main app
const app = Vue.createApp({
data() {
return {
newTodo: '',
todos: [
{ text: 'Learn Vue.js', completed: false },
{ text: 'Build a Vue app', completed: false }
]
}
},
methods: {
addTodo() {
if (this.newTodo.trim()) {
this.todos.push({
text: this.newTodo.trim(),
completed: false
})
this.newTodo = ''
}
},
removeTodo(index) {
this.todos.splice(index, 1)
}
}
});
app.mount('#app');
<div id="app">
<h1>My Todo List with Components</h1>
<input
v-model="newTodo"
@keyup.enter="addTodo"
placeholder="Add a new task"
/>
<ul>
<todo-item
v-for="(todo, index) in todos"
:key="index"
:todo="todo"
@delete="removeTodo(index)"
></todo-item>
</ul>
</div>
Summary
The Vue instance is the heart of every Vue application. It serves as the root of your component tree and provides:
- Reactive data binding through the
data
property - Methods for handling user interaction
- Computed properties for derived values
- Watchers for responding to data changes
- Lifecycle hooks for running code at specific times
Understanding the Vue instance is essential for building robust Vue applications. As your applications grow, you'll typically organize your code into components, but the core concepts of the Vue instance apply to those components as well.
Exercises
- Create a simple Vue application that displays your name and a greeting message.
- Extend the todo app to store todos in localStorage, so they persist when you refresh the page.
- Create a Vue instance with a data property that changes every second (like a timer).
- Build a simple form with validation using computed properties.
- Create a Vue application that loads data from an API when it's mounted.
Additional Resources
- Vue.js Official Documentation: Application & Component Instances
- Vue.js Lifecycle Hooks
- Vue.js Methods and Computed Properties
- Vue Mastery: Intro to Vue 3
Now that you understand the Vue instance, you're ready to move on to more complex Vue features and build more dynamic applications!
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)