Getting started with Vue.js

An experienced developer friend told me recently that Vue.js is becoming more and more popular at his software consulting firm. So when I needed an alternative to Angular in my latest project, a custom “bugs & issues” tracker, I decided to investigate what all the fuss was about!
Creating my first Vue app
The “Getting Started” documentation on vuejs.org is well written and easy to follow. Of course, I made my share of beginner’s errors, which I’ll document here.
My goal is to dynamically display a list of bugs & issues, populating each row with one element in from an [issues] array.

Here’s where I’ll be building my Vue app (issues.js):
var issuesApp = new Vue({
el: '#issues-container',
data: {
foo: 'bar'
}
})And here’s where I pull in the relevant scripts in issues.html:
<script type="text/javascript" src="vue/dist/vue.min.js"></script>
<script type="text/javascript" src="issues.js"></script>Gotchas
Cannot find element
If you try to load both of the above scripts in the <head> of the document, you’ll get this nasty error:
vue@2.4.2:485 [Vue warn]: Cannot find element: #issues-containerMoving the script tag that references vue.min.js to the bottom of the page (immediately before the closing body tag) didn’t help.
What worked was adding the defer attribute to the file where I invoked new Vue().
<script type="text/javascript" src="issues.js"></script>I’m not sure if this is the ideal solution, but it worked for getting my first app up and running quickly.
Getting helpful feedback in the console
I found this helpful tidbit in the documentation for the vue-devtools Chrome Extension:
If the page uses a production/minified build of Vue.js, devtools inspection is disabled by default so the Vue pane won’t show up
I switched to the un-minified version of vue.js that comes with the Vue node module, and presto, I’m able to view more warnings that are helpful for a newbie.
[Vue warn]: v-bind without argument expects an Object or Array value(found in <Anonymous>)
This warning led me to understand that this is not the correct usage of v-bind:
Foo is <span v-bind="foo"></span> <!-- don't do this! -->It turns out that curly brackets work just fine:
<div>Foo is {{foo}}</div>Tips for beginners in the console
Side note: I love the tips that the developers of Vue provide in the console:

Why doesn’t every library do that?!? (Pssst… Angular, I’m looking at you! 😉)
Deprecated lifecycle hooks
I found out the hard way that some lifecycle hooks referenced in older tutorials existed in previous versions of Vue but have been deprecated in Vue 2.0. For example, ready() is no longer available, but mounted() or created() are alternatives, depending on when you want the function to run:
var issuesApp = new Vue({
el: '#issues-container',
ready: function() { // this won't work
this.loadIssues();
},
created: function() { // but this will
this.loadIssues();
},
})Vue.component headaches
I tried creating my first component as follows:
issues.js:
Vue.component('issueitem', {
template: '<div>Hi!</div>'
})issues.html:
<issueitem></issueitem>But I got the following error:
Unknown custom element <issueitem>. Did you register the component correctly?Well, Vue, if I knew how to register the component correctly, we wouldn’t be having this conversation, now, would we??? 😄
It turns out that in addition to calling Vue.component, you have to add a components key when you invoke new Vue().
var _issueitem = Vue.component('issueitem', {
template: '<div>Hi!</div>'
});var issuesApp = new Vue({
el: '#issues-container',
data: {
foo: 'bar'
},
components: {
issueitem: _issueItem
}
});
Indicating an external template file in a component
templateUrl, which I was familiar with from Angular, does not exist in Vue.
Vue.component('issue', {
templateUrl: 'views/issue.html' // don't do this!
})As a temporary stopgap, I placed my template markup directly into .component, bookended by single backticks:
var _issueitem = Vue.component('issueitem', {
template: `
<div class="issue-row" id="{{issue.id}}">
<div class="issue-col">Site: {{issue.site}}</div>
<div class="issue-col">Issue: {{issue.issue}}</div>
<div class="issue-col">Page:{{issue.page}}</div>
<div class="issue-col">Browser:{{issue.browser}}</div>
<div class="issue-col">Severity: {{issue.severity}}</div>
<div class="issue-col"># Affected Users: {{issue.users}}</div>
<div class="issue-col">Status: {{issue.status}}</div>
</div>
`
});It feels a little uncomfortable plunking a big chunk of HTML in the middle of a JavaScript function, but my goal is to get this application up and running quickly [famous last words!], so I’ll leave this as is for now.
Scoping
Variables defined at the app level are not directly accessible inside components.
var _issueitem = Vue.component('issueitem', {
template: '<div>Foo is {{foo}}<div>' // foo is undefined
});var issuesApp = new Vue({
el: '#issues-container',
data: {
foo: 'baz'
},
components: {
issueitem: _issueitem
}
});
However, if you define the variable within the component, it will be accessible to the component’s template:
var _issueitem = Vue.component('issueitem', {
data: function() {
return {
foo: 'bar'
}
},
template: '<div>Foo is {{foo}}</div>'
);var issuesApp = new Vue({
el: '#issues-container',
components: {
issueitem: _issueitem
}
});
(Seems obvious now — duh!)
In summary
If you’re familiar with another framework like Angular, Vue.js will not seem completely foreign. As with many open-source projects, there are a few holes in documentation for beginners, but with a little digging, it was possible to create my first front-end Vue app in just a few hours.
I hope this list of gotchas helps other newbies out there!
A note on sources: a big thank you to to Ryan Chenkie, author of “Build an app with Vue.js,” to Joshua Bemenderfer, author of “Understanding Vue.js lifecycle hooks,” and to the many contributors on StackOverflow who have already asked and answered questions similar to mine!

