- Published on
The Differences: Vue.js 2 vs. Vue.js 3, What You Need to Know
- Authors
- Name
Good morning, my friends. In this article, we’re going to introduce the differences between Vue 2.x and Vue 3.x, making it easy for those who are already familiar with Vue.js 2.x to quickly understand the distinctions and relationships between the two versions.
Here, I will develop a simple table component using both Vue 2 and Vue 3 to demonstrate the differences in developing components with these two versions. By the end of this article, you’ll have a concept of the disparities in component development between Vue 2 and Vue 3 and be prepared for your journey with Vue 3.
Creating a Template with VueJs
For components, most of the code in Vue 2 and Vue 3 is very similar. Vue 3 introduces Fragments, which means components can have multiple root nodes. This new feature can reduce the need for unnecessary div wrappers between components.
In Vue 2 development, you may have noticed that each component is often wrapped in a div element, resulting in many layers of unnecessary div elements. Fragments address this issue.
Although we won’t show an example here, let’s stick with simple single-root-node components.
Vue 2 Table Template
<template>
<div class="form-element">
<h2>{{ title }}</h2>
<input type="text" v-model="username" placeholder="’Username’" />
<input type="’password’" v-model="’password’" placeholder="’Password’" />
<button @click="’login’">Submit</button>
<p>Values: {{ username + ' ' + password }}</p>
</div>
</template>
The only real difference in Vue 3 is data retrieval. In Vue 3, reactive Data
is contained within a reactive state variable, so we need to access this reactive state to get the data values.
Vue 3 Table Template
<template>
<div class="’form-element’">
<h2>{{ state.title }}</h2>
<input type="’text’" v-model="’state.username’" placeholder="’Username’" />
<input
type="’password’"
v-model="’state.password’"
placeholder="’Password’"
/>
<button @click="’login’">Submit</button>
<p>Values: {{ state.username + ‘ ‘ + state.password }}</p>
</div>
</template>
Establishing Data (Data)
This is where Vue 2 and Vue 3 differ the most. Vue 2 uses the Options API, while Vue 3 uses the Composition API. The old Options API separates different properties: data, computed properties, methods, etc. The new Composition API allows us to use functions to split our code, making it more concise and tidy. Let’s compare Vue 2 and Vue 3 code to see the difference.
Vue 2 — Putting two data properties in the data object:
export default {
props: {
title: String
},
data () {
return {
username: ‘’,
password: ‘’
}
}
}
In Vue 3, we use a new setup() method, which is triggered when the component is initially constructed. To gain more control over reactive data, we can use Vue 3’s reactivity API directly. Here’s how to create reactive data:
import { reactive } from ‘vue’
export default {
props: {
title: String
},
setup () {
const state = reactive({
username: ‘’,
password: ‘’
})
return { state }
}
}
The reactive data constructed here can be used in the template via state.username
and state.password
.
Methods in Vue 2 vs. Vue 3
In Vue 2, the Options API allows us to define methods directly within the methods property. Here’s an example of how to do it:
Vue 2 — Defining a method within the methods property:
export default {
props: {
title: String
},
data () {
return {
username: ‘’,
password: ‘’
}
},
methods: {
login () {
// Login method
}
}
}
In Vue 3, the Composition API’s setup() method can also be used to define methods. Defining a method is similar to defining data — we declare a method and return it within setup(). This allows the method to be called within the component.
Vue 3 — Defining a method using setup():
export default {
props: {
title: String
},
setup () {
const state = reactive({
username: ‘’,
password: ‘’
})
const login = () => {
// Login method
}
return {
login,
state
}
}
}
Lifecycle Hooks
In Vue 2, you can directly call Vue’s lifecycle hooks within the component options. Here’s an example using the mounted hook to trigger a function after the component is mounted:
Vue 2 — Using the mounted hook
export default {
props: {
title: String
},
data () {
return {
username: ‘’,
password: ‘’
}
},
mounted () {
console.log(‘Component has been mounted’)
}
}
In Vue 3, the Composition API’s setup() method contains most of what you need, including lifecycle hooks. However, in Vue 3, lifecycle hooks are no longer globally accessible; you need to import them separately. For example, you can use onMounted
to handle the mounted hook:
Vue 3 — Using onMounted within setup():
import { reactive, onMounted } from ‘vue’
export default {
props: {
title: String
},
setup () {
// …
onMounted(() => {
console.log(‘Component has been mounted’)
})
// …
}
}
Computed Properties
Let’s try adding a computed property to transform the username
into lowercase in both Vue 2 and Vue 3.
In Vue 2, defining a computed property is straightforward. We add it to the computed property section of the component:
Vue 2 — Defining a computed property:
export default {
// ..
computed: {
lowerCaseUsername() {
return this.username.toLowerCase();
},
},
};
In Vue 3, things are a bit different. Vue 3 allows for more granular control over what dependencies are imported, avoiding unnecessary imports that can affect performance or bundle size. In Vue 3, you need to explicitly import computed from Vue, and then you can define a computed property within setup():
import { reactive, onMounted, computed } from ‘vue’
export default {
props: {
title: String
},
setup () {
const state = reactive({
username: ‘’,
password: ‘’,
lowerCaseUsername: computed(() => state.username.toLowerCase())
})
// …
}
}
Receiving Props
Receiving and using props is where the most significant difference between Vue 2 and Vue 3 lies. In Vue 2, this
refers to the current component, not a specific property. Therefore, you can directly use this
to access prop values.
For example, in Vue 2, you can access and log the title
prop like this:
Vue 2 — Accessing and logging a prop:
mounted () {
console.log(‘title: ‘ + this.title)
}
In Vue 3, this
no longer directly accesses props, emits events, or other component properties. Instead, Vue 3’s new setup()
method receives two parameters:
props
: Immutable component props.context
: Exposed Vue 3 properties (emit, slots, attrs).
So, in Vue 3, receiving and using props looks like this:
Vue 3 — Receiving and using props within setup()
:
setup (props) {
// …
onMounted(() => {
console.log(‘title: ‘ + props.title)
})
// …
}
Emitting Events
Custom events in Vue 2 are quite straightforward, but Vue 3 provides more freedom and control over emitting events.
For example, suppose we want to trigger a login
event when the submit button is clicked. In Vue 2, we call this.$emit
and pass the event name and a parameter object:
Vue 2 — Emitting a custom event:
login () {
this.$emit(‘login’, {
username: this.username,
password: this.password
})
}
In Vue 3, since this
no longer directly accesses component properties, including $emit
, we need to handle custom events differently.
Fortunately, the setup()
method’s second argument, the context
object, contains an $emit
method that works similarly to $emit
in Vue 2. We can use it to emit custom events within setup()
:
Vue 3 — Emitting a custom event within setup()
:
setup (props, { emit }) {
// …
const login = () => {
emit(‘login’, {
username: state.username,
password: state.password
})
}
// …
}
Conclusion
In conclusion, I believe Vue 3 brings a whole new development experience to front-end developers, offering greater flexibility and control. If you’ve learned or worked with React and are now exploring Vue, you should be excited because many usage patterns are now very similar!
The new Composition API allows for more decoupled code, especially in large front-end applications where this effect becomes more pronounced. Additionally, on-demand imports provide finer control, allowing for better management of project performance and bundle size.
I hope this article has been helpful to you.
This is the second article in my Vue.js Base Knowledge series, which aims to help a Vue.js beginner to becoming an expert.
This article will also be added to my “Vue.js Base Knowledge” library. If you’re interested, please feel free to follow me and the library.