Common Vue.js Gotchas

Published on April 4, 2017

Joshua Bemenderfer

Common Vue.js Gotchas

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

As with any framework, Vue has a few oddities that might take newcomers a little while to get used to, and many stumble over. Here, we’ll attempt to list a number of those and how to work with and/or around them.

Installation & Building


While Vue is often cited as a *“progressive”* web framework, allowing you to only use the pieces you need little by little, if you wish to create a full application, you will definitely want a proper build system. Most commonly in the Vue community, Webpack is used.

Recognizing that Webpack is often hard for first-timers to understand, Vue offers vue-cli to help get a working scaffold ready for your app from the start. We use this in a number of our articles to establish a common base.

Versions (1.x vs 2.x)

Unlike with Angular 1 vs Angular 2, the two major releases of Vue, while changing many things under-the-hood, have very, very similar usage. So much so that if you don’t know what to look for, you won’t recognize if a component is written for Vue 1 or Vue 2. This can be problematic as compiled distributed files for Vue 1 won’t work with Vue 2, and vice-versa.

Here are a few signs of which version a component has been written for:

  • Does the component have a ready() (Vue 1) or a mounted() (Vue 2) method?
  • Does the component use v-bind.sync= attributes? Those are Vue 1 only.
  • Are filters being used outside of mustache expressions ({{}})? (ie. @click="thing() | debounce 200") That was removed in Vue 2.
  • Are partials being defined or used anywhere? (Vue 1)
  • Do you see any render() functions? The virtual DOM (and therefore, the render method) was added in Vue 2.
  • Are $broadcast and $dispatch being used anywhere? Those were removed in Vue 2 in lieu of a global event bus and provide / inject.
  • Is the order of arguments in v-for (index, item) or (key, val) (Vue 1) or the inverse (Vue 2)?

An advantage of these minor differences is that it’s incredibly straightforward to port a component from Vue 1 to Vue 2.


Vue’s reactivity system is great, but it doesn’t handle quite everything. There are a few edge cases that Vue can’t detect. (Yet. Hopefully when ES6 Proxies are widely supported these caveats will be gone.)

  1. When properties are added or removed from an object, Vue won’t know about it and won’t make them reactive.
  2. You can’t add new properties to the root data object directly, but you can use Vue.set(this.data, ‘propname’, value)
  3. Vue can’t detect when a particular index value changes in an array from setting it directly through array[index] = value. The workaround is to use Vue.set(array, index, value)
  4. Vue can’t detect when the length of an array changes. Use splice instead.


If using a module system, always make sure to Vue.use(plugins) before you try to use them. Otherwise you may be left scratching your head as to what went wrong. For some reason a lot of people seem to have trouble with this.


v-for without keys

Using v-for on arrays of objects without a key binding can result in some very strange rendering when the array changes. This is because Vue doesn’t know how to identify which objects changed without a key binding. The solution to this is to use :key=“obj.prop” to bind to a unique property on the object. (This is, in-fact, required in recent versions of Vue.)


  • Custom delimiters (via the delimiters) option are only available in the standalone build. (The one most often loaded via a script tag.) They don’t work in the npm versions.

HTML interpolation.

Many people don’t seem to know about the v-html binding which allows you to render html as an element’s children.

NOTE: You cannot use bindings and the likes inside of injected HTML. Use components for that instead.


The ref attribute on an element allows you to access the rendered element inside of your component. USE THIS IN PLACE OF IDS, IF YOU REALLY NEED THEM!

Hopefully this list helped you out! We plan to expand it in the future as needed.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us

About the authors
Default avatar
Joshua Bemenderfer


Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
Leave a comment

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Featured on Community

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel