Heya!
Thanks to the Vue Core team, we can try out the most anticipated Vue 3 which has a lot of great improvements and features to look forward.
Currently it's in the beta release, and if you want to get hands-on with the latest changes you can try to install it and followup the changes in their github release.
As a VueJS developer, I have experienced the current code implementation of Vue 2, and when I tried the Vue 3, I noticed there are some breaking changes. But don't get me wrong, I personally like the breaking changes as I believe it will help to improve the code quality and lesser chance of unexpected bugs. Also, these breaking changes are coming from the agreed RFC by the Vue Core team, so check them out for more detail.
Alas, here we go!
Vue app initialization
In the Vue 2, usually the plugin installation will be done in the global instance of the Vue
object, and then we create a new
instance of the Vue to initialize the Vue app. For example:
// Vue 2 example of initialization
import Vue from 'vue';
import Vuex from 'vuex';
import App from './App.vue';
// install vuex plugin
Vue.use(Vuex);
const store = new Vuex.store(/* store configuration object */);
// initiate the vue app
new Vue({
store,
render: (h) => h(App),
}).$mount('#app');
This implementation has a flaw if you need to create multiple Vue
app in the same page. Since it uses the global Vue
instance to install the app, you can't initiate multiple Vue
app with different plugins to be installed. This can lead to the pollution of the Vue instance.
In the Vue 3, plugin installation and app initialization are immutable from the original Vue instance, since you must initiate the Vue app first before installing the plugins.
// Vue 3 example of initialization
import { createApp } from 'vue';
import { createStore } from 'vuex';
import App from './App.vue';
// initialize the store object
const store = createStore(/* store configuration object */);
// create the app and install the store
createApp(App)
.use(store)
.mount('#app');
Notice that there's no global Vue
defined and mutated here. With this, now you can be sure that every plugin used on each application is specific and won't pollute other Vue
app. Profit! 😄
More details and the reason behind in the RFC: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0009-global-api-change.md
Allow multiple v-model
, and deprecate model
option
💓 Before I make anyone panic here, please note that this changes on v-model
API is not affecting the usage of v-model
in the native elements like <input>, <select>, <textarea>
, etc.
The model
option that I referred on the title above is the model option that we use for custom v-model
on the custom component. So yes, this breaking change is only meant for the custom component that uses model
option, as mentioned here that it will be removed in the Vue 3.
In the Vue 2, you can only define one v-model
to have a two-way data binding. If you need multiple props to have two-way data binding, you can use .sync instead.
// Vue 2 example of v-model and sync
<my-custom-component
v-bind:title.sync="title"
v-model="visible"/>
Having v-model
and .sync
directive takes more learning curve while they are doing similar things. Thus, in Vue 3 the .sync
are deprecated, and then you can use multiple v-model
instead! 😍
Vue 3 example of v-model
<my-custom-component
v-model:title="title"
v-model:visible="visible"/>
More consistent, so less bikeshedding with your teammates, profit! 😄
More details and the reason behind in the RFC: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0011-v-model-api-change.md
Event Bus is deprecated
Do you love the concept of Event Bus in Vue?
If yes, then this might disappoint you a bit. Vue has no official documentation for Event Bus, but the API built in the Vue 2 instance allows us to create a publish-subscribe object with the vm.$emit
and vm.$on
method.
// Vue 2 example of event bus
const eventBus = new Vue();
// subscribe
eventBus.$on('sandwich-made', () => console.log('sandwich made!'));
// publish
eventBus.$emit('sandwich-made');
There is a good motivation behind this changes, because Vue encourages more state-driven data flow, which data are passed from parent components to its child, and events are emitted from the child to the parent component. Profit! 😄
But of course using Event Bus pattern is still allowed in the Vue 3. If you still need it, you can install any 3rd party library or write your own.
More details and the reason behind in the RFC: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md
filter
is deprecated
Filter is one of the early feature introduced by Vue to easily map your rendered value. It is usually used for price tag, currency, and capitalize.
The usage of filter is usually to beautify your vue template code:
// Vue 2 example of filter
<div class="name">{{ user.name | capitalize }}</div>
<script>
import capitalize from './filter/capitalize';
export default {
/* vue configuration */,
filter: {
capitalize
}
}
</script>
Filter are encouraged for simplicity and re-usability. But, it is also replaceable with methods
because there is no difference in terms of performance. Removing filter
will encourage more explicit methods to be defined on each component, and if you need to reuse the filter function on multiple components, it can just be simply imported and registered as part of the method.
// Vue 3 example of filter
<div class="name">{{ capitalize(user.name) }}</div>
<script>
import capitalize from './filter/capitalize';
export default {
/* vue configuration */,
methods: {
capitalize
}
}
</script>
This is just my personal opinion, but if you're looking forward for the Vue 3 Composition API, you might notice that filter
can also be easily replaced as well by manually return the filter function in the setup.
// Vue 3 composition api setup example
import { useState, useRefs } from 'vue';
import capitalize from './filter/capitalize';
setup () {
const data = {
user: { name: 'Albert' }
}
return {
...useRefs(data),
capitalize
}
}
Deprecating filter
will help us to code more consistently and no more bikeshedding on deciding whether the function shall be registered in the filter
or method
. Profit! 😄
More details and the reason behind in the RFC: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0015-remove-filters.md
Summary ⭐
With the upcoming release of Vue 3, the changes are going to a better direction for the sake of the code quality. All of these breaking changes are considered carefully in the RFC, so feel free to check and contribute to the discussion!
Lastly, thank you for going through this article! I hope this help anyone that consider to migrate their existing Vue 2 application to the Vue 3, to be aware of the changes and be prepared!
What do you think of the breaking changes? Your comment and suggestion to help me improve this documentation and my writing skill is very much appreciated!
note: This documentation will be updated according to any changes to be made, before it finally reach the stable release.
Top comments (6)
I do still think that removal of the Event Bus is a big blow for developing complex frontend.
there will always be systems that will need that kind of architecture.
not all the time it is parent and child, there are systems that will need component to component data transfer and removing the Event Bus is a big blow
It's not like you now cannot use any event bus in your app. It's just that you can't use a shallow Vue instance to create one. Npm is full of event bus packages, a lot of them weighing in at ~300 bytes.
Removing bloat and keeping the core of Vue lean is essential to move the framework forward and keep it maintainable.
The new changes is absolutely necessary and right for the betterment of VueJS.
Great article 👍👌.
Thanks for feedback!
The new composition syntax is miscalculated move from the Vue team, and with a change like this the past in most cases tell a story of the future. Just like React and Angular, the community will be split or forced to run with this new trendy syntax. The core values of Vue are now depreciated.
I may understand your concern.
In my opinion, Vue Composition API is a blessing for experienced developer that has more opinionated codebase and needs to abstract and compose the functionality, with proper typings. But, it's also not necessary for simple use-case of Vue component.
The concern that I can see is that, any new libraries or tutorial will move towards composition API, which splits the gap further with the common Vue interface.