Understand VueJS in 5 minutes
I’ve been playing with VueJS recently. I’m impressed. It’s simple, powerful, super fun and incredibly popular. Even a moron like me can do interesting things with it rapidly. It just goes to show that anybody can do great things with it. Do you have five minutes in front of you ?
Once upon a time
2012 in the New York area. At that time Evan You is living his best life learning Javascript. He’s doing side projects left and right for laughs. One of them explodes in popularity on Hackernews ! Evan didn’t know, but he just got Google’s attention.
Very quickly hired at Google, his role is to create “experimental projects” for innovative ideas. He uses a lot of vanilla Javascript. He tries AngularJS and other frameworks, but he rages instantly on it. He doesn’t find the freedom he needs. So he had an idea : extract the best part of these frameworks and make his own light and malleable framework for his own personal need.
In July 2013, the first commit of VueJS was made. For the record, VueJS was to be called Seed.JS. But it was taken on NPM! Since its framework is centered around the view part, Evan wanted something that looked like “View” in English. He went to google translate and translated “View” into several languages. He came across the French translation “Vue” and found it cool. A few minutes later, VueJS was published.
In 2014, the first version of VueJS arrived on the Internet. The project doesn’t explode right away. But like the creator of Laravel, more and more people are talking about it. Today, VueJS is in the big league.
What is VueJS ?
VueJS is a Javascript frontend framework to create user interfaces. You’re going to say “one more?” and the answer is yes. Except it’s a little different.
First, it’s interesting to understand that VueJS was designed to be incrementally integrated. That means if you have an existing frontend application, you don’t have to redo everything. You can make a new part in VueJS and quickly integrate it with the rest.
VueJS is also the most is easy to pick up of all the frontend framework. That’s what attracted me as a backend developer in the first place. Very quickly, I did some frontend stuff that worked ! I was shocked! Within a few hours of reading the doc and testing stuff, I had understood all the basics. I was already shipping frontend.
VueJS also takes good ideas from its competitors. It allows data binding. The data and the DOM are coupled and reactive to changes. We also find the concept of virtual dom with VueJS. The DOM is not directly changed, it goes through the virtual DOM.
We also find the organization by component. This feature allows you to divide your application into several sub-components that each manage their own life and are reusable. Let’s imagine you want to make a list of images: you can make a component that manages an image and a component that manages a list of image components.
That’s all well and good, but how does it work?
How does it work?
For once I cheat a bit and show some code in advance to better understand what’s coming next. Hello World!
<!DOCTYPE html> <html> <head> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app">{{ message }}</div> <script> const data = { message: "Hello World !" }; new Vue({ el: "#app", data: data }); </script> </body> </html>
VueJS focuses on the view part of your application. To do so, the framework is partly inspired by the MVVM architecture pattern. VueJS will link your DOM, the view part, with your view instance, the Model-View part. These two parts are linked by the data-binding system.
Finally, the data in your view instance is the Model part. It will provide your application with data. The Hello World code schematized looks like this.
A VueJS application is composed of one or more components. When the instance of the global application is launched, there is first a root instance. This is root instance is composed of a tree of components which have their own root instance.
But what happens to the life cycle of your instance when you create the component with new Vue()? I wanted to make my usual silly schema but it turns out that the official VueJS doc is just EXCELLENT. It’s rare to have a good documentation. So I’m just going to pump their schema.
I’ll let you admire it and figure out what’s going on. The only thing that might be unclear is the difference between “created” and “mounted”.
- Created means that the element is only available in the View-Model part.
- Mounted in VueJS means that the DOM element has been rendered in your page and you can manipulate it.
OK great, now let’s get our hands dirty.
Show me the code
I’m gonna show you a piece of code I made for a personal need. A simple responsive gallery with only three components. We start with the root app.
app.vue
<template> <div id="app"> <action v-bind:message="messageAction"></action> <grid v-bind:photos="photos"></grid> </div> </template> <script> import action from './components/action.vue' import grid from './components/grid.vue' export default { name: 'App', components: { action, grid }, data: function () { return { photos: [ { id: 0, url: "https://i.imgur.com/p3IKY9G.jpg" } ], messageAction: "It's working !" } } } </script> <style> * { box-sizing: border-box; } body { margin: 0; font-family: Arial; } </style>
On the template side I start by declaring my root app in a div. Inside there are two other components (action and grid). Note how I pass the data that comes from the instance seen in the components with the v-bind directives.
On the script side, I import the components to use them in the app we export. We declare the data, the pictures and a message, which is reactive to changes.
On the style side I integrate very simple CSS that is global to the whole project.
Next up, the action component.
action.vue
<template> <div class="callToAction"> <h1>{{ message }}</h1> </div> </template> <script> export default { name: 'callToAction', props: { message: String } } </script> <style scoped> .callToAction { position: absolute; height: 100%; width: 100%; padding: 0; margin: 0; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; align-items: center; justify-content: center; } h1 { color: red; background:black; padding: 10px; } </style>
The action component is simply a text that we put in the middle of the page and that will be a call to action for the user. I use the {{ message }} syntax to display the message that comes from the app.
Note also that the style part is “scoped”. This means that the CSS in question has effect only in this component. This is very useful to separate the style scope of each component.
grid.vue
<template> <div class="grid"> <div v-bind:key="grid.id" v-for="grid in grids" class="column"> <photo v-for="photo in grid" v-bind:photo="photo" v-bind:key="photo.id" ></photo> </div> </div> </template> <script> import photo from './photo.vue' export default { name: 'grid', components: { photo }, props: ['photos'], computed: { grids: function () { const grids = [] const deepClonePhotos = JSON.parse(JSON.stringify(this.photos)) const gridsToMake = Math.ceil(deepClonePhotos.length / 2) - 1 for (let index = 0; index <= gridsToMake; index++) { const currentGrid = [] for(let i = 0; i < 2; i++) { if(deepClonePhotos.length) { currentGrid.push(deepClonePhotos.shift()) } } grids.push(currentGrid) } return grids } } } </script> <style scoped> .grid { display: -ms-flexbox; /* IE10 */ display: flex; -ms-flex-wrap: wrap; /* IE10 */ flex-wrap: wrap; padding: 0; } /* Create four equal columns that sits next to each other */ .column { -ms-flex: 25%; /* IE10 */ flex: 25%; max-width: 25%; padding: 0; } /* Responsive layout - makes a two column-layout instead of four columns */ @media screen and (max-width: 800px) { .column { -ms-flex: 50%; flex: 50%; max-width: 50%; } } /* Responsive layout - makes the two columns stack on top of each other instead of next to each other */ @media screen and (max-width: 600px) { .column { -ms-flex: 100%; flex: 100%; max-width: 100%; } } </style>
The grid component is the one that will make the logic to display image grids in relation to the data it receives from the app. In the template part I create a column every two images. In these columns I display my two images. I do this using another photo component. You will notice the use of the v-for directive to browse my lists.
In the script part, I use props to get the data passed by the v-bind in the app. Then I use the computed function to create a new grids variable with the data of the pictures.
photo.vue
<template> <img :src="photo.url" alt ="" /> </template> <script> export default { name: 'photo', props: ['photo'] } </script> <style scoped> .column img { vertical-align: middle; width: 100%; } </style>
The photo component just allows me to isolate the display of the photo in a corner. It’s quite simple, but it allows me to change a lot of things on this side in the future without having to touch the logic above! As usual, I put a little codesandbox, you can play with it and see it all in action.
Epilogue
We’ve been talking VueJS for more than five minutes now. You have to understand that after reading the doc quickly I created this first application in a few hours. The handling of this framework is crazy and so pleasant. Frankly I advise you to test it, it’s enjoyable!
Thinking Vue is simple and easy is one of those famous misconceptions made by those not very familiar with Vue possibilities. In reality in order to use its full potential there is a lot to learn as with other frameworks. Thats why many problems posted on the Net have scarce or no replies at all. Because it is not easy