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:
<input type="text" class="name-field" v-model="name" />
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:
<input v-model="username" type="text" autocapitalize="off" /> <input v-model="password" type="password" />
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