learning javascript? try Vue
What JavaScript framework should I learn?What JavaScript framework should I learn?
…is the question I get asked most from beginners. It’s understandable, with currently 1_5 choices _of frameworks on the comparison site TodoMVC.com. Starting to learn a framework is equal parts information overload and fear we’ll chose “wrong” and waste our time because we didn’t know any better.
The truth is: most of the knowledge you acquire in one JavaScript framework transfers to the others. It’s not the same as picking which stock investment to purchase. If you, as a beginner, never felt you got an adequate answer to the “which framework” question, it’s because it’s not a frequent question after learning that first framework. Once you learn one, the second takes less time. The same is true for the third, fourth, and fifth. Eventually they’re all tools in your toolbelt. JavaScript frameworks aren’t different languages; they’re simply different approaches to putting together the same thing: JavaScript.
I believe Vue is the best framework to start with. It has the quickest ramp-up time (no webpack, terminal commands, boilerplate, etc.) and a shorter time to mastery (thanks to well-written docs). Vue is the quickest path to accomplishing having that first framework under your belt, and I see it as the best introduction into the world of frameworks without it being a mere “stepping stone” or “shortcut.” Still need convincing?
- Unlike jQuery, Vue has predictable state management, so you can build big, complicated apps using Vue (“state management” means your data has a nice, clean, central place to live). jQuery is known to be a headache at scale because that’s not what it was designed for. And, curiously, Vue is actually smaller in filesize (77.2k) than default jQuery (84.6k).
- Unlike Ember, Angular, or React/Preact/Inferno, Vue is up and running in seconds. No bundlers, compilers, webpacks, Typescripts, or terminal commands that are, at best, time sinks, and, at worst, incomprehensible. Configuration and tooling aren’t bad things, but to the beginner it can be a major headache. When you eventually find a need for all that high-powered stuff, Vue’s got you covered with hotness like this PWA template.
- Also unlike React/Preact/Inferno, Vue.js is simple and straightforward. There’s a huge leap between learning beginner HTML and CSS to understanding the virtual DOM and JSX that most tutorials gloss over. Starting with Vue first and React second will make sense a whole lot quicker than vice-versa (for the record, I highly recommend learning React as your second framework).
- Vue is cutting-edge as of 2017, and growing rapidly, unlike older frameworks like Backbone or Knockout. You can learn Vue in confidence it won’t be phasing out next year.
- Unlike vanilla JS (no framework), Vue teaches good code habits. It forces you to think about your application in a healthy way (data-first). Further, frameworks are big time and money-savers for teams because every person is organizing code in a very similar pattern.
OK, OK. Vue it is. But where do I start?
In this ’pen, you can see that you enter your name in a text <input>
and it displays on a card.
Maybe this isn’t a useful piece of UI that every site needs, but it’s a reduced example of a core
concept of JS frameworks: data.
⚛️ It all revolves around data
You may have heard “data” used all different ways: big data, data-driven, etc. For our purposes, we’ll define data as **variable bits of information our application needs to handle. **Sometimes you may also hear the words state or model; all three words generally refer to the same thing (sometimes data refers more to database/API information while state refers more to client-side, in-memory changes, but I won’t get into those semantics here). When it comes to building your own application, before you begin, it’s good to ask questions like:
- What is the data in my application?
- Do I need to mutate the data?
- Where am I displaying data?
- Does the data need to be stored somewhere (database, etc.)?
1. What is the data in my application? For our purposes, “data” is everything the user does that our website responds to. Button clicks, text fields, checkboxes, mouse movements…if our site should respond to it, it’s data we need to keep track of. In our example, we have one piece of interactive data: that text field.
2. Do I need to mutate my data? Once a user enters their name, we’re not mutating (altering) that data. We’re keeping the user’s name exactly as they entered it, capitalization, spelling errors, spaces, and all.
3. Where am I displaying my data? We’re displaying our data on our stylized name card, so that data needs to go into the HTML somewhere.
4. Does the data need to be stored anywhere? We don’t need to worry about storing the data anywhere; this is just for funsies.
Now that we have a better understanding of our data, Vue will start to make a lot more sense, because now it’s time to build!
📛 Example 1: The Glorified Name Tag
Same example as above. First, we’ll get some markup on the page and load Vue. I’ll skip explaining the CSS, but everything is in the CodePen if you want to take a look. Here’s our basic markup:
<body>
<div id="app" class="app">
<input type="text" class="name-field" />
<div class="name-tag">
Hello, my name is
<div class="name-show"><!-- name goes here --></div>
</div>
</div>
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script>
new Vue();
</script>
</body>
Want to follow along looking at the entire code? Here’s the finished repo.
So we want to take that text field data, and display it where we have our <!-- name goes here -->
HTML comment. We start by invoking a Vue()
function
that initializes Vue and gets it ready for our app (when you see parentheses in JavaScript, that’s
how you know it’s a function). Ignore the new
word in JavaScript for now. Vue needs that, and it’s
important, but it’s
complicated to explain
at first.
This is technically working and correct, but it’s not doing much. We have to give Vue instructions and data. Let’s pass one parameter to our function in the form of an object:
new Vue({ el: '#app' });
Data types, according to JavaScript
Let’s take a short break to run through some common data types:
- String:
text values surrounded by quotes:
'Hey! I’m a text!'
or'I ate three hotdogs today.'
. - Number:
number values, without quotes:
42
or3.14
. You can perform math on numbers:42 * 2
or3.14 + 1 — 2
. - Object:
comma-separated key–value pairs, surrounded by curly brackets. You can place any property into
an object value, like string, number, or even object or
array:
{ key1: 'some value', key2: 'some other value', key3: 3.14 }
. Objects are most useful when referencing one thing at a time. - Array:
comma-separated value list, surrounded by square brackets. They’re basically objects without
keys:
['some value', { stuff: thing }, 3.14]
. Arrays are most useful when referencing the entire collection at once.**_ _We’re not using Arrays in this post, but they’re mentioned because they’re frequently used alongside objects.
There won’t be a pop quiz on this stuff, and it’s OK if this doesn’t stick yet. For now, just think: “I see quotes! That means ‘string’” or “I see curly brackets! That means ‘object.’”
Take a second look at { el: '#app' }
. Now you know that’s an object (curly brackets), with a
string (quotes) inside. Neat!
Back to the code: from the official docs, we learned to start Vue with the following:
new Vue({ el: '#app' });
We set el:
(short for “container element”) to whatever the ID is for our containing element
(#
means “ID,” the same as CSS). For that dynamic text field data, we need to give that an
identifier. How about “name
?” That should be easy to remember.
<body>
<div id="app" class="app">
<input type="text" class="name-field" />
<div class="name-tag">
Hello, my name is
<div class="name-show">{{ name }}</div>
</div>
</div>
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script>
new Vue({ el: '#app', data: { name: 'Timmy' } });
</script>
</body>
We added 2 things:
- We used 🐰🎩 Vue magic and placed
{{ name }}
in our HTML where we wantname
to show (this is Vue, but the double curly brackets are actually a common syntax shared by React, Ember, Angular, and more to display data in HTML) - We gave Vue a
data
object (curly braces inside curly braces—object within an object!), and we declared aname
value of'Timmy'
(string). Remember: we decided whatname
was called, butdata
was something Vue told us about from the docs. It might be confusing until you learn which parts are Vue’s by reading the guides.
If you save and load up that page in a web browser, you can see our name card showing Timmy
! We’re
close, and our last step is connecting our input field to what we’ve done. One last addition will
complete it:
By adding v-model="name"
to our input, that tells Vue we want this input to get and set the
value for name
. In other words, we want our Vue data to be mutable by our text field. Typing
into that text field should update our data, and our data should update that text field. v-model
is another super-special Vue thing we only would know about if we
read the docs.
This is called a two-way binding when something can both get and set data. We don’t have
anything else interacting with our name
data, but if we did and that value changed in some other
part of the app, then the text input would update as well. Two-way binding.
If you’re still a little confused about {{ name }}
, remember what I said earlier: it’s all about
data. When you use the double curly brackets in HTML, you’re asking Vue to display data on the
page.
👉 To see the full code, check out Example 1 in the repo.
Hint: if you’re confused about what things should go inside data
, try saving anything the user
interacts with—form fields, checkboxes, button clicks, etc. Need to keep track if a user checks a
checkbox? Throw a v-model
on that checkbox and add it to data
. If a user has opened a modal?
When a user clicks that button, save that open state in data
with on:click=""
(we won’t get into actions & methods in
this blog post, but
_Composing Reusable Modal Dialogs in Vue.js _is
a good one to bookmark). If a user does it, make a new data key! Over time, you’ll learn to identify
what you need to keep track of, and what you don’t.
🎯 Extra challenge
Try adding the Hello, my name is
text into Vue’s data
object, and displaying it on page with
double curly brackets.
🥋 Example 2: Computational Kung-fu
There’s a little more going on in the UI here, but we really only went from one piece of data to
two. Once again, we’re using v-model
because we’re working with form fields. The inputs look like:
Protip: use _autocapitalize="off"_
to be kind to your mobile users and prevent accidental
capitalization.
That’ll plug into our Vue app just as nicely, only this time let’s give ourselves some room to work with line breaks:
new Vue({
el: '#app',
data: {
username: '',
password: '',
},
});
We set both to ''
(an empty string), because we expect those to be text. So we set Vue’s
expectations appropriately. We’re doing the same two-way binding from before, and we have access to
that data in Vue. But we’re going to do a little more than just display what a user entered on
another part of the page. That was easy-peas; we’re shooting for the big leagues here. We want to
accomplish the following:
- For
username
, we want to show “username taken” if a username is taken out of a list of names - For
password
, we want to show “weak password” if it’s too short, etc.
So that leaves the question: how do we give feedback based on data, without mutating the data?
Making data interactive with Vue’s computed properties
The quickest explanation for how computed properties work might be a metaphor. Think of a
lightswitch in your house. That switch can have one of two values: off
or on
. That’s all the
switch itself does. Of course, that switch’s purpose is to control something else nearby. Usually
that’s a light bulb, but it could also be a fan, garbage disposal, or—like one particular switch
that was never fixed at my mother’s house—the power to an entire room. Whenever the position of that
switch changes, so does the behavior of whatever it’s wired to. If the switch is data, then its
lightbulb/fan/disposal is its computed property, _meaning it updates based on what the source data
(the switch) does._
Let’s add a computed
key to our Vue.js options object, and we’ll start with the first item above,
our username
feedback. Let’s make up a name—usernameTakenMessage
:
new Vue({
el: '#app',
data: {
username: '',
password: '',
},
+ computed: {
+ usernameTakenMessage: function () {
+ // something should go here…
+ },
+ },
});
According to Vue’s references, computed properties must always be a function, so we’ll just add an
empty one for now. Let’s make up a small list of fake usernames to check against: bill
, sally
,
petunia
, and gregory
. Let’s add those using JavaScript’s comparison operator (===
) and the or
operator (||
):
new Vue({
el: '#app',
data: {
username: '',
password: '',
},
computed: {
usernameTakenMessage: function () {
- // something should go here…
+ if (this.username === 'bill' || this.username === 'sally' || this.username === 'petunia' || this.username === 'gregory') {
+ return 'Username taken';
+ } else {
+ return '';
+ }
},
},
});
In our HTML, if we wanted to see username
, we’d just write {{ username }}
. But when we’re inside
Vue()
, because of JavaScript reasons, we have to write this.username
. this
is a special word
in JavaScript. This is actually directly related to that new
word, but again, that’s something you
can
learn outside your blog post
when you’re ready to. For now, we’ll just remember it and move on.
Let’s walk through the key lines here:
usernameTakenMessage: function () {
we named our own key here, and used a name we wanted to. We’re setting it to a function because Vue demands itif (this.username === 'bill' || this.username === 'sally' …
we’re usingif
, which starts a condition. It means exactly what you think it does.===
is used to compare if 2 things are equal. We’re saying “ifthis.username
equalsbill
” we want something to happen. We have these set between logical operators (||
) that mean “or.” In plain language, this whole line means: “if username is bill, or if username is sally, or if username is petunia, or if username is gregory, then (do something).”return 'Username taken';
Hey! it’s our old friend, the string.return
means stop executing the function at that point and report back with whatever value is listed. From the previous line, we’re saying “if the user entered any of these names, then we wantusernameTakenMessage
to give us the text'Username taken'
.else {
only works following anif
. It basically catches whateverif
didn’t. So this will only execute if the user did not enter “bill,” “sally,” “petunia,” or “gregory.”return '';
We’re saying we want an empty string if the username is available
The rest of the program is simply closing curly brackets. Like objects, functions also use curly
brackets to demarcate where they begin and end. In case you were wondering, yes, it’s very confusing
when you have a lot of }
together, and I frequently have one too many, or too few, and an error
happens. Welcome to being a programmer!
Handling password
We’re now showing to the user whenever a username is taken, but we still need to display password strength. Let’s make up some goals off the top of our head based on how we think it should work.
- Let’s give users a chance to start typing before we display anything. So if the
length
is0
, we won’t show anything. Otherwise: - 1–5 characters long: weak
- 6–9 characters long: decent
- 10+ characters: strong
Following that logic, let’s add another computed property, passwordStrengthMessage
:
new Vue({
el: '#app',
data: {
username: '',
password: '',
},
computed: {
usernameTakenMessage: function () {
if (
this.username === 'bill' ||
this.username === 'sally' ||
this.username === 'petunia' ||
this.username === 'gregory'
) {
return 'Username taken';
} else {
return '';
}
},
passwordStrengthMessage: function () {
if (this.password.length === 0) {
return '';
}
if (this.password.length >= 1 && this.password.length <= 5) {
return 'Weak';
}
if (this.password.length >= 6 && this.password.length <= 9) {
return 'Decent';
}
if (this.password.length >= 10) {
return 'Strong';
}
},
},
});
passwordStrengthMessage: function () {
same as before, Vue computed properties have to be a function.if (this.password.length === 0) {
For any string, you can put.length
and it’ll return how many characters long it is (including spaces). Here, we’re comparing to a number, so we don’t need the quotes around0
.return '';
Let’s return an empty string if the password field is empty.if (this.password.length >= 1 && this.password.length <= 5) {
The<=
and>=
mean “less than or equal to,” and “greater than or equal to.” The=
always has to come last. We’re saying “if the password length is between 1 and 5 characters, (do something).” The&&
means “and,” the counterpart to||
(or). It’s always two ampersands and I’m not really sure why; it just do.return 'Weak';
Show this message if passwordlength
is 1–5- For the rest of the lines, they’re similar in nature—I’ll skip the explanation.
Displaying the messages
Displaying these computed properties is as simple as it was in the first example: simply write
{{ usernameTakenMessage }}
and {{ passwordStrengthMessage }}
in your markup to display the
feedback:
<input v-model="username" type="text" autocapitalize="off" />
<div class="feedback">{{ usernameTakenMessage }}</div>
<input v-model="password" type="password" />
<div class="feedback">{{ passwordStrengthMessage }}</div>
Now, if a user types a taken username, that {{ usernameTakenMessage }}
will either be empty, or
Username taken
. Likewise, the {{ passwordStrengthMessage }}
will either show Weak
, Decent
,
or Strong
.
We’re now giving the user proper feedback! Only, it’s still unstyled. To complete this project, we’ll need to add or hide some error classes.
Vue Class Binding
Adding or removing classes in Vue is called
class binding. If you’ve used jQuery, you may
have used $().addClass()
or $().removeClass()
. Vue does it a bit more automatically, and—you
guessed it—based on data. We specify a bound class with v-bind:class=""
(:class=""
for short).
Let’s say we want 2 state classes. If it’s valid, we’ll add .is-valid
. If invalid, .is-invalid
.
In Vue, we use an object to bind properties:
{ 'value I want to show': computedPropertyThatControlsIt }
:
<label :class="{ 'is-valid': true, 'is-invalid': false }"></label>
Tip: in Vue, it’s not just _:class_
you can control; you can let Vue bind to any HTML
attribute, such as _:href_
, _:src_
, etc.
That will render <label class="is-valid">
, always. We can make it a bit more responsive if instead
of true
or false
we hook that up to a new computed property:
computed: {
usernameIsValid: function () {
if (this.username === 'bill' || this.username === 'sally' || this.username === 'petunia' || this.username === 'gregory') {
return false;
} else {
return true;
}
},
You can see we copy & pasted a lot of our function code from usernameTakenMessage
. Only this time
we’re returning false
instead of 'Username taken'
and true
instead of ''
. We can update our
markup now:
<label :class="{ 'is-valid': usernameIsValid, 'is-invalid': false }>
That works! But we still need something for false
. Fortunately, JavaScript has a solution to that:
!
. The exclamation mark at the beginning of a reference means opposite or inverse.
!true === false
, and vice-versa. So, instead of making a whole other computed property, let’s
save time and simply use:
<label :class="{ 'is-valid': usernameIsValid, 'is-invalid': !usernameIsValid }"></label>
Amazing how much time a single !
can save.
From this point, we are:
- Giving username feedback if username is taken
- Giving password feedback if password is too short
- Adding/removing styling classes based on user data
_But wait! _you might be thinking (the 5 of you that read to this point). _We haven’t built the
strength meter! Or the _passwordIsValid
_computed property! _Rather than make this blog post
longer, I’ve given you the tools to inspect them yourself from the CodePen and the
repo. Much of that is re-using concepts and code we used
in the previous examples. But leave a comment if you’re still having trouble.
👉 To see the finished product, check out Example 2 in the repo.
🎯 Extra challenge 1
We start out with a ✅ for username
, and a magenta ✕ for password
. This isn’t a great user
experience. Can we add more code to the usernameIsValid
and passwordIsValid
to return
undefined
until a user has typed something in
(see the repo if you’re stuck—it’s not in the CodePen)?
🎯 Extra challenge 2
The if
/else
conditionals within passwordStrengthMessage
was simplified for readability and
clarity, but we could write that more efficiently. For example, this accomplishes the same, with
less redundancy:
passwordStrengthMessage: function () {
if (this.password.length === 0) {
return '';
}
else if (this.password.length < 6) {
return 'Weak';
}
else if (this.password.length < 10) {
return 'Decent';
}
else {
return 'Strong';
}
}
Are there any other ways you can shorten the if
/ else
rules further? Note: this uses
_else if_
, which can be tricky to use correctly at first. There’s no shame in sticking to
plain-old _if_
/_else_
_ in the beginning._
Help! Something’s not working!
You’ll naturally encounter errors when working with JavaScript, and so, Google Chrome’s console tab will probably be open the entire time you work in JavaScript (right-click > Inspect > Console). It sounds dumb, but this is how JavaScript talks to you. Everything that goes on gets placed here. You can also use plugins like Vue.js devtools for even more feedback.
If you get an error, and you’re not sure what it means, just do what us professionals do and Google it. 99/100 times you’ll get a quick answer to your problem.
Yet another reason I love Vue is the error messages are very informative. Often times it’ll tell you
the exact line and character number your code errored at. Beyond
that, use [console.log()](https://developer.mozilla.org/en-US/docs/Web/API/Console/log)
like it’s going out of style, and it’ll also help to set up
linters and debuggers. There are many tools you can
use, but the only wrong way to develop JavaScript is to not use the Console tab.
Summary
So through this blog post, this is how much JavaScript you encountered:
- Strings:
'string'
- Numbers:
42
- Arrays:
[]
- Objects:
{}
- Functions:
function () { }
- Conditionals:
if
/else
- Comparison operators:
===
(equals),||
(or), and&&
(and) - Return:
return
- The mysterious
this
andnew
And you learned the following things about Vue.js:
- Data:
data: { name: '' }
- Displaying data:
{{ name }}
- Computed Properties:
computed: { computed1: function() { } }
- Class binding:
:class="{ 'is-valid': usernameIsValid }"
That’s a pretty good base to build a lot of things! As your knowledge about JavaScript grows, you’ll encounter crazy things like ternary operators, and you’ll fill in your knowledge gaps as you encounter code in the wild. But, arguably, through this blog post you’ve already encountered most of what you’ll use on a regular basis in JavaScript, and most of what I use in Vue.
The only critical Vue things I haven’t addressed yet are
Event Binding and
Methods.
Composing Reusable Modal Dialogs with Vue.js
is a good one to learn about v-on:click
and the methods: { }
object. And, of course, there’s
still a lot more to Vue like list rendering and
watchers, but those usually become apparent
when you have a need for them.
Many blog posts end with encouragement to read something vast and boring like all the MDN pages. Rather than do that, I believe the best way to learn about JavaScript is building things for yourself.
Don’t know what to build? Try doing a monthly challenge like the Daily UI Challenge but making it in code. Or search for “UI” on Dribbble and recreate things there (give credit to the original designer)! Or tackle that app idea you’ve been thinking about. Coding can be infinitely creative if you don’t box yourself in. Or if you want to brush up on your pure JavaScript chops, try the 30-day JavaScript challenge by
With Vue.js under your belt, now the sky is the limit.
Further Reading
- Intro to Vue.js Animations by
[Sarah Drasner](https://medium.com/u/c2509fce86ff?source=post_page-----ad27c7b6687f--------------------------------)
- A Vue.js Introduction for people that know just enough jQuery to get by,
by
[Matt Rothenberg](https://medium.com/u/2ed8b724390a?source=post_page-----ad27c7b6687f--------------------------------)
- The official Vue.js Guide
- Vue Awesome: the official collection of Vue.js plugins and addons