Authors: Chelsey Ong, Lu Lechuan
Reviewers: Gilbert Emerson, Ong Shu Peng
Vue is an open-source JavaScript framework for building user interfaces. It is designed to improve code quality and maintainability.
This is a simple example to show how easy it is to integrate VueJs into your web project:
The main HTML file:
<body>
<div id="root">
<h2>{\{ message }\}</h2>
</div>
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>
<script src="the_path_to_the_javacript_file.js"></script>
</body>
This is inside the JavaScript file:
new Vue ({
el: '#root',
data: {
message: "Hello World"
}
});
Note that {\{
and }\}
should be {{
and }}
respectively, due to the limitations of MarkBind.
Step-by-step explanation of the code:
Step 1: Import Vue Content Delivery NetworkCDN and the JavaScript file in the main HTML file.
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>
<script src="the_path_to_the_javacript_file.js"></script>
Step 2: Create an instance of Vue (Vue is an object) in the JavaScript file; bind the instance to one of the component in our html file (e.g. create a component with id root
and bind it with the instance of Vue).
In this case, only the root
component can be accessed in Vue while the rest are unaffected. This is how we progressively plug in Vue into our projects.
new Vue ({
el: '#root',
});
<div id="root"></div>
Step 3: Specify our data (message: "Hello World") in the instance of Vue Class.
data: {
message: "Hello World"
}
Step 4: Pass the message to the HTML file using double curly brackets.
<div id="root">
<h2>{\{message}\}</h2>
</div>
Step 5: Open the browser and we will see "Hello World" being displayed:
Hello World
Mutating of Data in the DOM
In Vue, the state of the data can be directly modified.
Let's say, there is a variable called message
in your app. To modify message
, you can do the following:
this.message = 'Hello Space';
When message
is changed, the view will be re-rendered to show the new message. So you can say, the DOM is "reacting" to the changes in message
.
Two-way binding
v-model
is a Vue directive used to bind the DOM input field to its data variable.
This allows the DOM variables and data to be "in sync", regardless of which one is being updated first. In other words, if you change the input value, the bound data will change, and vice versa.
<input type="checkbox", v-model="isChecked">
<label for="checked">Select</label>
</input>
When the checkbox is selected, isChecked
is set to true
. If the program sets isChecked
to false
, then checkbox will be unselected.
This reduces any extra step required to manually update the data.
2-way binding is useful for updating input form bindings such as checkboxes or drop-downs, where new data is entered by users and then updated in the view.
Conditionals and Loops
v-if
allows you to conditionally insert/remove elements based on the truthfulness of the binding value.
v-for
allows you to loop through and render a list of items.
Following the previous checkbox example, if you want to display a list of messages when the checkbox is checked, you can do the following:
<div v-if="isChecked">
<div v-for="message in messages">
<li>{\{message}\}</li>
</div>
</div>
Passing Data From Outer to Inner Components
When you have components that are nested within each other, data is passed from the outer component to the inner component via props
, where props
are just custom data shared between the components.
This follows the 1-way data flow encouraged by Vue, which ensures that data can only be changed by the component itself and also allows bugs to be easily traced in the code.
To pass props to a Vue component, v-bind:<prop-name>
is used. A demonstration of passing props is shown in the code segment below:
Vue.component('todo-list', {
props: ['item'],
data: ['totalCount'],
template:`
<div class='todo-list'>
<p>Total:{\{this.totalCount}\}</p>
<p>{\{item.name}\}: {\{item.count}\}</p>
</div>
`
})
<todo-list
v-for='item in items'
v-bind:key='item.id'
v-bind:item='item'
></todo-list>
to-do list
contains item
, i.e. to-do list
is the outer component and item
is the inner component.
Note that props
is passed from the outer component to the inner component while data
is kept private within a component.
Emitting Events
However, what if the user decides to update the item.count
? The data for item.count
has to be passed from item
to todo-list
so that totalCount
can be updated inside todo-list
.
How do we do that if we have to follow the 1-way data flow rule?
In situations where the inner component has to pass data back to the outer component, the inner component has to emit custom events and the outer component will update after listening to these events.
You can think of emitting events like putting out a flyer about an event. If someone is interested in this event, he or she can gather more information through reading the flyer.
Vue.component('item', {
data: ['count', 'name'],
template: `<button v-on:click="$emit('increased-count', count+1)">Increment item count</button>`
})
/* Inside todo-list component */
template: `<item v-on:increased-count="updateCount" v-for="item in items"/>`
When the button is clicked, the item
component will emit a custom event named increased-count
while the todo-list
component listens for this event and executes its own updateCount
method.
Computed Properties
This is useful when you want to compose new data based on the data that has changed.
Instead of calling methods to do that whenever data has changed, computed properties will do it for you automatically.
computed: totalCount() {
return this.items.reduce((sum, item) => sum + item.count);
}
Unlike the use of methods, this updating of totalCount
will only be triggered when the number of items
in the list or any item
's count
changed.
Since computed properties are cached and will not be processed every time the page refreshes, this can greatly improve the efficiency of your application.
Watched Properties
Watched properties are used to call other functions when a particular data has been updated, such as independent operationsasynchronous operations.
For example, when a new item
is added, we want to send a notification to our friend to alert him or her about the change.
A watched property on items
can be added so that a notification can be sent whenever items
has changed.
watch: {
totalCount: function() {
this.totalCount = this.items.reduce((sum, item) => sum + item.count);
// notify friend about the change
}
}
This may look quite similar to Computed properties
.
To decide which is more suitable for your feature, here is a brief comparison:
Watched property | Computed property |
---|---|
used for running expensive operations | used for updating data for dependencies |
executed every time page refreshes | uses cached data and executes only when changed |
watches for change in 1 property | creates a new property that is updated when 1 or more dependencies change |
Lifecycle Hooks
Every Vue instance goes through a series of initialization steps when it is created, i.e. setting up data observation, compiling the template, mounting the instance to the DOM, and updating the DOM when data modifies. Along these steps, Vue runs functions in the background called lifecycle hooks, allowing users to add code at each stage that could improve its rendering speed.
The following diagram shows all lifecycle hooks and their specific execution stages:
Figure 1. Vue's Lifecycle Diagram
To run code at a specific stage, you can just define the corresponding hook function and add your code within the function.
For example, the created
hook can be used to run code right after the Vue instance is created:
Vue.component('todo-list', {
...
created: function() {
console.log("to-do list is created.");
}
})
For more detailed information about Vue lifecycle hooks, visit here.
Now that we know what Vue is, let us look at some benefits it has to offer.
Vue is very easy to learn. Compared to other framework such as Angular and React, Vue is simple in terms of API and design. Learning enough to build non-trivial applications typically takes less than a day. An example is provided below:
Iteration in React:
The JavaScript file in ReactJs
var Iteration = React.createClass({
getInitialState() {
return {
array: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
}
},
render() {
this.state.array.map(function(date) {
return (
<span>{date}</span>
)
});
}
});
ReactDOM.render(<Iteration />, document.getElementById('array'));
The HTML file in ReactJs
<div id="array"></div>
Iteration in Vue:
The JavaScript file in Vue
var Iteration = new Vue({
el: '#array',
data: {
array: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
}
});
The HTML file in Vue
<div id="array">
<span v-for="date in array">{\{date}\}</span>
</div>
Vue is designed from the ground up to be incrementally adoptable. The core library is focused on the view layer only, and is easy to pick up and integrate with other libraries or existing projects. This means that if you have a large application, you can plug Vue into just a part of your application without disturbing the other components. A quote from Evan You - the founder of VueJs is as follows: > Vue is a more flexible, less opinionated solution (than Angular). That allows you to structure your app the way you want it to be, instead of being forced to do everything the Angular way (Angular requires a certain way to structure an application, making it hard to introduce Angular into an already built project). It’s only an interface layer so you can use it as a light feature in pages instead of a full blown SPA (single-page application). > > -- [source]
Vue is perfectly capable of powering sophisticated single-page applications when used in combination with modern tooling and supporting libraries.
Vue syntax is simple and this can make the HTML pages very clean. This would allow user interfaces built by Vue to be more maintainable and testable.
Like any other framework/library, Vue has its share of disadvantages.
Relatively Small Size Community:
Vue is a relatively new JavaScript framework as compared to Angular and React. The size of the community for Vue is therefore relatively small. Although small size community means you can differentiate yourself from other JavaScript developers, it also means there are fewer resources such as tutorials and problem-shooting guides.
Language Barriers:
A majority of users of Vue are the Chinese as Vue is developed by a Chinese American. He is supportive of the Chinese community and hence a lot of the existing plugins are written in Chinese. There might be some language barriers for an English speaking developer seeking for Vue resources.
Detailed comparison of Vue with other JavaScript frameworks can be found from:
Links to VueJs tutorials and practices: