If you need to upgrade your Vue app to version 2, most of your code is good to go. There are a couple of features though that need some modifications. Some are simple renaming, some are more involved.
Upgrading to Vue.js 2
How to do it...
To give your migration a head start; Chris Fitz (a member of the Vue core team) created a little helper app that will scan your code and guide you in the migration:
- Install Vue Migration Helper with the following npm command:
npm install -g git://github.com/vuejs/vue-migration-helper.git
- Navigate to your app folder.
- Run the program with the following command:
vue-migration-helper
All the lines in which a change is necessary will be highlighted. Once you are finished updating, or if you still have doubts, you should take a look at the official documentation migration page at https://rc.vuejs.org/guide/migration.html.
How it works...
Reading through the documentation will help you understand the critical points that need to be updated. Here I will provide you a rationale for some of the most challenging modifications.
Deprecation of $broadcast, $dispatch, and the events option
Both methods $broadcast and $dispatch are now merged in the $emit method with the same syntax as the old version. Unfortunately, replacing every instance of $broadcast and $dispatch with $emit is not guaranteed to always work because the pattern used to manage events is a little different now.
In Vue 1, you had events follow a path either downward (for $broadcast) or upward (for $dispatch), and horizontally (for $emit) through the hierarchical tree.
To be honest, I never liked having two (three if you count the old $emit) methods for emitting events. It was confusing even in the smallest contexts because you had to ask yourself is this event for parents or children? Most of the time it was not that important of a distinction, you just wanted your method to fire. But there is no such thing as a free lunch; we have to add a moving part to our system to make everything work in the new paradigm.
Now all events should pass through one or more central hubs. The role of this central hubs can be taken by a Vue instance since they implement the necessary interface.
When emitting an event consumed by v-on, you're good to go by replacing $broadcast with $emit, since the event doesn't have to travel far. On the other hand, if you are defining an interface for a component in terms of events, you will have to say goodbye to the events option since it will not work anymore. This is the direct consequence of having all the events passing through a hub--the events option wouldn't know where to register all the events. This is the trade off for having a single emitting method: it fires in every direction but only in a precise piping.
Let's say you have a dedicated empty Vue instance that will act as an event hub:
var eventBus = new Vue()
If you are writing a teapot component and you want to register the brew event, you will write in the created hook something like the following:
new Vue({
el: '#app',
components: {
comp1: {
template: '<div/>',
created () {
eventBus.$on('brew', () => {
console.log('HTTP Error 418: I'm a teapot')
})
}
},
comp2: {
template: '<div/>',
created () {
eventBus.$emit('brew')
}
}
}
})
And with the HTML:
<div id="app">
<comp1></comp1>
<comp2></comp2>
</div>
Every time the brew event is emitted with eventBus.$emit('brew'), the console will output a message.
Any component you'll write can act as an event hub. You also have the API methods $off which deletes listeners, and $once, which listens for an event but only once.
Deprecation of array filters
If you had a lot of filtered v-for lists, I have bad news for you. Even if in the wild the most common use for filters was with v-for, the community chose to remove this feature. The reason is mainly because having a lot of filters, often piped together, was hard to reason about and thus to maintain.
The new recommended way to filter a list is with a computed property. Luckily for you, we have an entire recipe on how to do that. See the recipe Filtering a list with a computed property in the next chapter.
Deprecation of Vue.config.delimiters
Custom delimiters are not at the component level. If you want, you can have two different components using different delimiters.
This is fairly easy to upgrade and allows you to write components intended to be used inside other template engines:
<div id="app">
{!msg!}
</div>
new Vue({
el: '#app',
data: {
msg:'hello world'
},
delimiters: ['{!','!}']
})
Renaming of life cycle hooks
Life cycle have now a more consistent naming that will help with remembering their names in the long run:
Old hook | New hook |
init | beforeCreate |
created | created |
beforeCompile | created |
no equivalent | beforeMount |
compiled | mounted |
ready | mounted |
attached | no equivalent |
detached | no equivalent |
no equivalent | beforeUpdate |
no equivalent | updated |