Vue.js Developers

Looking to hire a Vue.js expert?

If you're looking for a freelance or remote Vue developer, join our brand new Vue.js Freelance and Remote Jobs Facebook group. This group is moderated for quality and is completely free to use.

If you're a developer looking for work, feel free to request membership.

Join Here

Latest Blog Posts

Advanced Vue Debugging: A Detective Story

Advanced Vue Debugging: A Detective Story

Modern frameworks like Vue.js do a ton for you. They manage DOM updates, maintain component lifecycles, and more.

Layer on higher level frameworks like Nuxt.js and even more is taken care of you. The plugin system lets you mix in behavior into all of your components automatically. Layouts, pages, and components are all seamlessly interwoven behind the scenes.

But one of the key questions is - what happens when things break down? When something goes wrong, and there is so much happening behind the scenes outside of your code, how do you debug it?

How do you follow the complex interweaving of runtime code, framework code, third party plugins, and your own code? It’s almost like unraveling a murder mystery. So much so, that I decided that the right way to talk about it might be to tell it as an unraveling mystery.

So here we go. Follow me as we walk through debugging a recent tricky bug I ran into, tracing the “culprit” down and along the way learning what types of forensic tooling we have at our disposal.

The setup

The bug occurred for me in a client application where I was using the vue-select component.

I updated the version of the vue-select package from v2.4.0 to v2.5.0 in order to get a new feature, but upon testing I found that the package was no longer working right.

In particular, this plugin allows you to type into an input, and it will automatically filter down the list of available options. After upgrading, that filtering wasn’t working.

My first assumption was that something in the way I was using the component was no longer supported. I looked at the documentation, and it looked like everything I was doing was right… in fact there was an example almost identical to the way I was using it.

I pulled down the package repository and put my example into it - it worked fine there. So clearly something weird was going on. Time to really dig into debugging.

Starting place - the console

My first stop was to open up the browser console and see if there was a javascript error. Maybe something else in my application was breaking, and the component was not getting fully set up.

While I didn’t find an error, I did see an odd pair of warnings:

Vue Warn Messages

‘Method “filterBy” has already been defined as a prop’ - that seemed like a hint. Maybe I was defining filterBy somewhere I shouldn’t? But searching through my code turned up nothing at all.

Looking into the vue-select source code was no more illuminating. I could see filterBy being defined as a prop, but no redefinition anywhere that might lead to this warning.

If there had been an actual error, I could have looked at the backtrace, but the warnings were coming from deep inside Vue internals.

Inspecting the component

To try to figure out what was going on, I used the Vue devtools to get a look at the component during runtime.

I knew that by default, the filterBy prop for vue-select should get set to a function that looked like:

function(option, label, search) {
  return (label || '').toLowerCase().indexOf(search.toLowerCase()) > -1
}

I selected the component in the Vue devtools and used the fact that it created a reference to the component named $vm0 to log out the function:

Log of filterBy function

Not a match at all! There was in fact a new function coming in… but when I searched through my codebase for the function signature filterBy (arr, search), or even just the arguments, nothing turned up.

And I still didn’t have any indication as to what was setting that new function, and when… only that something was in fact setting a new function.

Had I been a little smarter just then, I could have found it, but I didn’t. We’ll come back to what I could have done better, but first, the breakthrough that led to the solution:

The Breakthrough: Inserting a Breakpoint within warn

The breakthrough came when I realized that even though the warning was not happening in code that I could point to, it might have context that I could use to trace things down.

I clicked through to the warning code in the chrome DevTools and inserted a breakpoint.

Inserting Breakpoint

Reloading with this in place would let me then examine the state of the Vue vm at the time the warning was triggered.

Doing so, I saw nothing immediately obvious… the vm had filterBy defined, but it looked like the expected function.

So I started stepping forward in the debugger, and it popped me up to the function that had triggered the warning:

initMethods function

Ah-hah! Now we can directly inspect the method that is triggering the warning: it’s in the methods object:

methods object

The key is the link to source location. It was in the vendors.app.js bundle… if I had properly set up sourcemapping in the project to include node modules it would have pointed me straight to the source, but even without that I could click through and scroll up to see the webpack annotation to show me the source:

The Smoking Gun

The function was coming from vue2-filters, another 3rd party plugin that I had installed without worrying too much about it. This plugin installs a set of common filters, including some that are implemented as methods. One of those methods just happened to be named filterBy, and was clobbering the prop in vue-select.

Voila! The solution!

The shortcut that could have been

I mentioned earlier that if I’d been a little smarter, I could have found the issue when I first logged the filterBy function and saw it was different.

It turns out, had I inspected the $vm0 object that was my VSelect component, rather than just logging out the filterBy function, devtools would have actually let me click through to the source code at that point.

The Missed Reference

So I could have arrived at the solution one step faster. Interestingly, in the Firefox version of the devtools this reference does not appear to be there, but the warn approach still functions.

More Information and Resources

I hope you’ve enjoyed this “detective story” and gotten some ideas that will help you debug your Vue.js applications.

If you want to explore this debugging problem yourself, I’ve set up a barebones application with Nuxt 2.0 that reproduces the issue in github here.

All of these debugging examples were done with Chrome devtools plus the Vue Devtools Chrome extension. A similar extension exists for Firefox and also as an Electron app that will work in any environment.

You may also be interested in these additional resources:

read more

5 Most-Requested Features For Vue.js in 2018

5 Most-Requested Features For Vue.js in 2018

Vue is famed for its ease of use and simplicity. It achieves these qualities, in part, by having a focused and small API without too many extraneous features.

That said, users and maintainers are always thinking about potentially useful new features. This article discusses five of the most requested features from Vue’s GitHub issue board.

  1. Support for iterable protocol with v-for
  2. Multi-root templates (fragments)
  3. Reactive refs
  4. Custom v-model modifiers
  5. Package for custom renderers

It’s good to be aware of these feature requests, as some will make their way into coming versions of Vue, while the ones that don’t may help you better understand the design of Vue.

1. Support for iterable protocol with v-for

What is it?

When you think of iteration, you’ll most likely think of arrays. ES2015 introduced the iterable protocol which, when implemented, allows for any kind of object to be iterated using for...of. ES2015 also introduced new iterable data types like Map and Set.

Currently, Vue’s v-for directive can iterate arrays and plain objects, but not other iterable objects or data types. If you’re using a Map, for example, and you want to iterate it with v-for, you’ll first have to convert it to an array or plain object.

Note: maps, sets, and other new iterable data types are not reactive, either.

Why do users want it?

Since iterable objects and data types are officially part of the JavaScript language now, it’s inevitable that applications will utilize them for the benefits they offer.

If Vue is used as the UI layer for such an application, these objects and data types either can’t be iterated in the template or will need to pass through transformation functions.

Will it be added?

Maybe. The issue has been closed on GitHub, as the maintainers weren’t convinced that iterable objects and data types would commonly be used for UI state. Also, making iterable objects and data types reactive would take considerable work.

However, Vue’s observation system is to be refactored in version 2.x-next, which would be the ideal time to implement this feature.

Read more on GitHub.

read more

Can A Vue Template Have Multiple Root Nodes (Fragments)?

Can A Vue Template Have Multiple Root Nodes (Fragments)?

If you try to create a Vue template without a root node, such as this:

<template>
  <div>Node 1</div>
  <div>Node 2</div>
</template>

You’ll get a compilation and/or runtime error, as templates must have a single root element.

Typically, you’ll fix this problem by adding a “wrapper” div as a parent. This wrapper element has no display purpose, it’s just there so your template complies with the single-root requirement.

<template>
  <div><!--I'm just here for wrapping purposes-->
    <div>Node 1</div>
    <div>Node 2</div>
  </div>
</template>

Having a wrapper like this is usually not a big deal, but there are scenarios where having a multi-root template is necessary. In this article, we’ll look at why this is and provide some possible workarounds to the limitation.

Rendering arrays

The are some situations where you may need your component to render an array of child nodes for inclusion in a parent component.

For example, some CSS features require a very particular hierarchy of elements to work correctly, like CSS grid or flex. Having a wrapper between the parent and children elements is not an option.

<template>
  <!--Flex won't work if there's a wrapper around the children-->
  <div style="display:flex">
    <FlexChildren/>
  </div>
</template>

There’s also the issue where adding a wrapper element to a component may result in invalid HTML being rendered. For example, if you’re building a table, a table row, <tr>, must only have table cells, <td>, for children.

<template>
  <table>
    <tr>
      <!--Having a div wrapper would make this invalid HTML-->
      <TableCells/>
    </tr>
  </table>
</template>

In short, the single-root requirement means the design pattern of a components that return child elements will not be possible in Vue.

read more

Comparing the React and Vue Ecosystems with a Real-World SPA

Comparing the React and Vue Ecosystems with a Real-World SPA

React vs Vue - a favorite talking point among developers. Many people pick a framework and stick to it, never really getting to know the library they left behind. That’s mainly due to time; the only way to really get to know the ins and outs of a system is to use it, struggle with it, grow with it.

It’s just not efficient to spread your focus thin across similar tools, but aren’t you curious? I was.

Online you’ll run into articles that attempt to compare a to-do app or the like built with Vue and React, but rarely is a project so simple. With real applications, we’re worried about routing, state management, plugin compatibility, etc.

My question was not what are the differences between the Vue and React core libraries, but rather, how does building a real-world app compare in these frameworks? Which ecosystem of tools provides a better development experience for me when I’m building an SPA?

The Apps

I’ve been using Vue for about two years and developing for about eight. When I first started with Vue I decided I would learn it “out in the open” by open-sourcing a simple notes app that had fuller features like user-authentication using JWT and full CRUD note actions. This was partnered with a backend node API built using Koa.

Even though I don’t really have a specific need to change frameworks, I figured it would be a good idea to learn React. So I remade my koa-vue-notes app in React and open-sourced it as well. I figured the experience would broaden my understanding of JavaScript at the very least, and perhaps I’d find a new favorite tool.

Here’s the homepage of the app. The top is React, the bottom is Vue:

App Homepages

read more

Simple Vue.js Form Validation with Vuelidate

Simple Vue.js Form Validation with Vuelidate

Thanks to Vue’s reactivity model, it’s really easy to roll your own form validations. This can be done with a simple method call on the form submit, or a computed property evaluating input data on each change.

Using your form validation can quickly become cumbersome and annoying, however, especially when the number of inputs in the form increase, or the form structure gets more complicated e.g. multi-step forms.

Thankfully, there are great validation plugins for Vue like Vuelidate. In this article, we’ll be looking at how Vuelidate can be used to simplify:

  • Validation
  • Multi-step form validation
  • Child component validation
  • Error messages

We’ll also see how the Vuelidate-error-extractor plugin can be used to simplify error message display per input, or as an error summary above or below the form.

Basic validation with Vuelidate

Vuelidate is data-model oriented, meaning validation rules are added to a validations object in the component definition, rather than being added directly to input elements in the DOM.

The structure must resemble that of the form object, but the number of validation rules can be dynamic and change depending on which fields need validation.

export default {
  name: "FormComponent",

  data() {
    return {
      form: {
        name: "",
        email: ""
      }
    };
  },

  validations: {
    form: {
      name: { required },
      email: { required, email }
    }
  }
  ...
};

Here’s a live example:

read more