Related Blogs
Vue (pronounced /vjuː/, like view) is an open-source and progressive framework to build attractive user interfaces (UIs) and fully capable of creating single-page applications (SPAs). However, Vue is developed from the initial level with an incremental approach, not like simple monolithic applications. VueJs core library is only focused on the view layer and easily picks up and integrates with another library or existing projects. On the other hand, Vue is completely able to power sophisticated Single-Page Applications (SPAs) by using a combination of modern tools and support libraries. With this blog our Vuejs development team has taken a step to give you a complete guide on Vuejs setup and its best practices.
1. What is Vue.js?
Vue is a prominent and well-known JavaScript programming framework. Vue (pronounced /vjuː/, like view) is an open-source framework used to develop web-based user interfaces (UIs) with fully-functional single-page applications (SPAs). It is created from the scratch with an incrementally adoptable approach, unlike the traditional monolithic frameworks. Let us understand more about what is Vue.JS. The core functions can be easily integral with existing and are more focused on the view layer. The most liked feature of Vue is to empower sophisticated Single-page Apps by combining them with new-edge libraries and modern-day applications.
At the core of Vue.js is a reactive data-binding technique that is made quite simple to sync processes between your data to DOM. Whenever using JavaScript or jQuery to manually manipulate the DOM, often we write repetitive, imperative, and error-prone code. Vue.js embraces the concept of a data-driven view. In simple terms, we can use special syntax in our HTML templates like the “bind” attribute to bind DOM to the underlying data. After the bindings are formed, the DOM will be kept in synchronization with the data using an HTML template. Whenever you are updating or changing the data, the DOM updates and behavior accordingly. As a consequence, the majority of our application logic is focused on managing data directly rather than fiddling with DOM changes. It is making our code easy to write, maintainability and simpler to implement.
A reactive code-binding framework is at the heart of Vue.js, making it incredibly easy to keep the data and the DOM in sync. The code we write is always imperative, tedious, and error-prone when using jQuery to manually control the DOM. Vue.js promotes the notion of a view powered by results. In simple language, it implies that in our standard HTML templates, we utilize a unique syntax to “bind” the DOM to the underlying data. Until the bindings are established, the DOM will be maintained in sync with the data. Accordingly, the updates are made in the DOM as and when the details are modified. As a consequence of which, instead of playing around with DOM notifications, much of our application logic is now explicitly manipulating data. With this, code implementation, writing, and management are easier.
2. Advantages of VueJs
- Size: Size is the most important part when it comes to production and deployment, as the production-ready build of a full-featured Vue project weighs just a few MBs. So, developers required a minimum of seconds to download project source files. Vue is fast even though having a small size and can consistently outperform bulky frameworks.
- Rendering and Performance of Virtual DOM: The Document Object Model (DOM) is a model that includes HTML templates, styles, elements, and page content as objects that are saved in a tree structure form and produced by a browser when the page is loaded. When using a JavaScript file to make a change to an HTML page, the browser has to target the DOM nodes and update the information. Since there are hundreds of nodes in the DOM in modern apps, new changes can be computationally costly and delay the page down. Vue makes use of virtual DOM to get around this. This may be thought of as a replica of an original DOM that determines which elements to update without having to re-render the entire DOM. In this way, we can make page rendering pretty quick and increase application performance.
- Reactive Two-way Data Binding: Two-way data binding is a strong feature inherited from Angular that, when utilized correctly, may considerably speed up your development process. It cuts down on the time it takes to keep user input in sync with the application data model. Vue’s v-model directive supports two-way binding. The HTML is updated with the v-model directive whenever the model changes and updates the data model as well whenever the HTML template changes.
- Components in a Single File and Readability: In Vue, every element of your application is a component, which represents encapsulated User Interface components (UI). You can write the components in just HTML, CSS, or JavaScript files rather than being split into many files. Component-Based Architecture is an architectural strategy that splits the application code and offers a number of advantages:
- Component re-usability: You can create your own reusable custom Views and Components which can be easily integrated into an application.
- Readability of the code: Since all components are contained in distinct files, the code is simpler to read and comprehend, making it easier to maintain and correct.
- Simple unit-testing: Unit-testing is a QA activity that validates and verifies how the smallest pieces of an application operate independently. Having components makes this process much easier.
- Integration Capabilities and Flexibility: It allows the developer to write a template in HTML, JS, or JSX (JavaScript syntax extension). And because of its lightweight nature and Vue mainly relies on JavaScript, it can be easily created and/or integrated with existing applications.
- Easy to Learn: Needed basic knowledge of HTML, JavaScript, and CSS without in-depth knowledge of libraries like TypeScript to start developing an application. Vue is supported by the most major code editors, including such as Sublime, Atom, and Visual Studio Code, making implementation easy. Novices are warmly welcomed by the community, which actively participates in the Discord chat and forum by often answering queries.
- Documentation: The detailed documentation of Vue.js is mainly available on official sites, which is to helps the developer to learn and understand basic knowledge to develop an application. The document created is well-organized and covers all conceivable subjects, precisely covering everything from installation to more in-depth issues such as reactivity and app scaling.
- Lazy Loading of Vue Components: Vue.js provides an ability to handle lazy loading of components with routes, so on the DOM (Document Object Model), you can load components only when they are needed using routes. Vue.js combines the async component feature and web pack’s code splitting feature to lazy-load route components.
- Backed up PWA’s (Progressive Web Apps): Progressive Web Apps (PWA) is a concept in which web apps may be installed on client devices as native apps, giving consumers a native app-like experience in terms of dependability, performance, and engagement. PWA does necessitate the proper incorporation of new technologies and designs. Vue CLI (New Version e.g. > 3.x) provides an ability to create PWA and scaffold up a full PWA starter using a single command.
- Easy to integrate Testing tools: Unit testing a Vue.js application does not significantly differ from testing other types of applications. In the Vue.js application, we can easily integrate Unit testing frameworks like Jest, Mocha, or any other testing framework to perform Unit testing, component testing, or End-To-End testing.
3. Disadvantages of VueJs
- Language barrier: The Language barrier is one of the major drawbacks of Vue which is being reported by many developers. Vue is increasingly popular in China and some part of its discussions is in the Chinese language, which may cause trouble for only English-speaking developers.
- Complexity of reactivity: Each component in a Vue.js project has its own timer, which re-renders the data each time the component is triggered by a user. Only the data chunks that were triggered are re-rendered by the reactivity mechanism. The problem is that it’s not very efficient and frequently makes errors when reading data, therefore it has to be flattened.
- Limited plugins: Compared to React and Angular, common plugins are available which are useful to make development easier and are less complicated for Vue.js.
- Rapid version changes: With the rapid changes in the framework, one of the common issues developers may face is the functionality concerns occurring after integration with the latest version. This is the major noteworthy defect of Vue.js.
4. Environment Setup
There are a number of ways available to install VueJS. Some ways of doing it are displayed below.
1. First is by using the <script> tag in HTML file
<!DOCTYPE html> <html> <head> <title>Vue.js Application</title> <script type="text/javascript" src="Vue.min.js"></script> </head> <body></body> </html> |
<!DOCTYPE html> <html> <head> <title>Vue.js Application</title> <script type="text/javascript" src="Vue.min.js"></script> </head> <body></body> </html>
For this first, you have to download the Vue.js from the official site of Vue.js. (https://vuejs.org/guide/quick-start.html)
2. Using CDN
Create a new HTML page and include script tag to install VueJS using CDN link
<html> <head> <title>Vue.js Application</title> <script type ="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Vue.js"></script> </head> <body> Vue.js Application </body> </html> |
<html> <head> <title>Vue.js Application</title> <script type ="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Vue.js"></script> </head> <body> Vue.js Application </body> </html>
3. Using Vue CLI
CLI means Command Line Interface, which provides a full system for rapid Vue.js application development. It allows us to select which libraries our project will be using and it automatically plugs them into the project.
- Installing the CLI
To install the CLI (@Vue/cli), run the below command in the terminal.
npm i -g @Vue/cli |
npm i -g @Vue/cli
After you install the @Vue/cli npm package, all you have to do is create Single Page Applications with the use of Vue.
- Creating a Vue Project
To create a new project to use CLI, run the below command into the terminal which will start the Vue project creation with the name Vue-app.
Using Vue-app, ‘Vue create’
When you execute the command above, you’ll be given the choice of selecting a preset pre-set or manually selecting features. Pick the Manually select features option and enter the down arrow key and select the features.
Now once this step is done, you have an option to select Linter / Formatter. Select ESLint + Prettier option.
After that add the additional feature of Lint on save.
Select option to place configuration In dedicated config files.
Then you will be asked to save all these settings as a pre-set for future Vue projects. Select not to with N.
Once you select all the options, Vue CLI installs all third-party libraries and creates an application.
In order to view the application live in the browser, run the following commands:
cd Vue-app
npm run serve |
cd Vue-app npm run serve
When you open a project in the code editor, you will find the following structure created in your application.
5. Main Features Available with Vue.js
- Template
- Components
- Computed Properties
- Props
- Watchers
- Data Binding
- Event Handling
- Directives
- Rendering
- Modifiers
- EventBus
- State Management
5.1 Template
The template is where define HTML code and general markup for components. Any HTML code is valid through the Vue.js template. Vue template binds data to the DOM.
You can put the template into the File component. The displayed DOM (Document Object Model) may be declaratively bound to the underlying Vue instance data using Vue’s HTML-based template syntax.
Example:
<template> <h3>VueJs Application</h3> </template> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue {} </script> |
<template> <h3>VueJs Application</h3> </template> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue {} </script>
5.2 Vue Components
One of the most essential elements of Vue.js is components. They are reusable Vue instances and have their style, state, and markup. You can define a single component in one ‘.Vue’ file. This ‘.Vue’ file includes the HTML, CSS, and JavaScript for this component.
Example: App.Vue
<template> <h3>Vue.js Application</h3> </template> <style scoped> </style> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; @Component export default class App extends Vue {} </script> |
<template> <h3>Vue.js Application</h3> </template> <style scoped> </style> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; @Component export default class App extends Vue {} </script>
5.3 Computed Properties
Computed properties are used to quickly compute properties and respond to view. By default, the computed properties only have a getter, but it’s possible to have a setter as well. By having both, we can bind the input value correctly to the model.
Example:
<template> <div class="container"> <h3>Vue.js Application</h3> <hr> <div> <label>Enter Message: </label><input type="text" v-model="message" label="Message"> <p>Original message: {{ message }}</p> <p>Computed reversed message: {{ reversedMessage }}</p> </div> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue { private message: string = "Vue.js Application"; private get reversedMessage(): string { return this.message.split('').reverse().join(''); } } </script> |
<template> <div class="container"> <h3>Vue.js Application</h3> <hr> <div> <label>Enter Message: </label><input type="text" v-model="message" label="Message"> <p>Original message: {{ message }}</p> <p>Computed reversed message: {{ reversedMessage }}</p> </div> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue { private message: string = "Vue.js Application"; private get reversedMessage(): string { return this.message.split('').reverse().join(''); } } </script>
5.4 Props
Props are the ways of passing variables and other data around between different components. They are read-only and cannot be modified. Props should be declared with relative names and provided default values in the child component.
@Prop({ default: -1}) public count: number; |
@Prop({ default: -1}) public count: number;
We can declare prop and provide a default value to prop as per the above example.
Example: Add new Item.Vue (Child Component) in your application.
<template> <div> <div> <label>Item Price: </label><input type="number" v-model="itemPrice"> </div> </div> </template> <script lang="ts"> import { Component, Prop, Vue } from 'Vue-property-decorator'; @Component export default class Item extends Vue { @Prop({default: -1}) private itemPrice: number; } </script> |
<template> <div> <div> <label>Item Price: </label><input type="number" v-model="itemPrice"> </div> </div> </template> <script lang="ts"> import { Component, Prop, Vue } from 'Vue-property-decorator'; @Component export default class Item extends Vue { @Prop({default: -1}) private itemPrice: number; } </script>
Replace below code in App.Vue (Parent Component).
<template> <div class="container"> <item :itemprice="itemPrice"></item> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; import Item from "@/components/ItemComponent.Vue"; @Component({ components: { Item }, }) export default class App extends Vue { private itemPrice: number = 50; } </script> |
<template> <div class="container"> <item :itemprice="itemPrice"></item> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; import Item from "@/components/ItemComponent.Vue"; @Component({ components: { Item }, }) export default class App extends Vue { private itemPrice: number = 50; } </script>
5.5 Watchers
VueJS watch is one such feature that enables the developers to watch the behavior of all the components and check how it performs specific actions. Besides, the watcher also observes data property and enables the development team to detect when the data property changes.
Example: Replace below code in Item.Vue component.
<template> <div> <div> <label>Item Price: </label><input type="number" v-model="itemPrice" disabled=""> </div> <div class="mt-10"> <label>Quantity: </label><input type="number" v-model="quantity"> </div> <div class="mt-10"> <h4>Total Price: {{ totalPrice }}</h4> </div> </div> </template> <style scoped=""> .mt-10{margin-top: 10px;} </style> <script lang="ts"> import { Component, Prop, Vue, Watch } from 'Vue-property-decorator'; @Component export default class Item extends Vue { @Prop({default: -1}) private itemPrice: number; private quantity: number = 0; private totalPrice: number = 0; @Watch("quantity") private onQuantityChange(newValue: number, oldValue: number) { if (newValue !== oldValue && newValue > 1) { this.totalPrice = this.itemPrice * this.quantity; } } } </script> |
<template> <div> <div> <label>Item Price: </label><input type="number" v-model="itemPrice" disabled=""> </div> <div class="mt-10"> <label>Quantity: </label><input type="number" v-model="quantity"> </div> <div class="mt-10"> <h4>Total Price: {{ totalPrice }}</h4> </div> </div> </template> <style scoped=""> .mt-10{margin-top: 10px;} </style> <script lang="ts"> import { Component, Prop, Vue, Watch } from 'Vue-property-decorator'; @Component export default class Item extends Vue { @Prop({default: -1}) private itemPrice: number; private quantity: number = 0; private totalPrice: number = 0; @Watch("quantity") private onQuantityChange(newValue: number, oldValue: number) { if (newValue !== oldValue && newValue > 1) { this.totalPrice = this.itemPrice * this.quantity; } } } </script>
The watcher function is assigned to have a look at optionally accepted new property value that can be the first parameter and also watch the old property value that can be the second parameter.
private onQuantityChange(newValue: number, oldValue: number) { // TODO: } |
private onQuantityChange(newValue: number, oldValue: number) { // TODO: }
5.6 Data Binding
Reactive data binding is a very popular feature of VueJs. It is the core feature that can define data reactivity. It specifies the details about which component data is in sync with DOM. The process to sync the data is done automatically without any interference from the development team.
- Single-direction Data binding
The variable is just bound to the DOM in one-way data binding. VueJS is a technology that can easily handle the updates of DOM in a way that when the value of a variable gets changed nothing goes wrong.
Example: App.Vue component
<template> <div class="container"> <h4>{{message}}</h4> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue { private message: string = "VueJs Application"; // changing in value of message will be reflected in the DOM automatically. } </script> |
<template> <div class="container"> <h4>{{message}}</h4> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue { private message: string = "VueJs Application"; // changing in value of message will be reflected in the DOM automatically. } </script>
- Two-way data binding
When it comes to implementing the two-way binding in the VueJS technology, it can be done with the use of the v-model directive. When the input value in the form is changed, this model catches the updated UI elements or event changes, and then it starts updating the data property value with the new one. Basically, here the UI element gets updated if the value of the data property changes.
Example: App.Vue component
<template> <div class="container">> <label>Enter Message: </label><input v-model="messageValue" type="text"> <h4>Message: {{message}}</h4> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue { private messageValue: string = ""; } </script> |
<template> <div class="container">> <label>Enter Message: </label><input v-model="messageValue" type="text"> <h4>Message: {{message}}</h4> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue { private messageValue: string = ""; } </script>
5.7 Event Handling
By using the “v-on:” directive we can listen to DOM events and execute some JavaScript code when events are triggered.
Example: App.Vue component
<template> <div class="container"> <button v-on:click="incrementCount">Increment Count</button> <h4>Total Count: {{count}}</h4> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue { private count: number = 0; private incrementCount() { this.count++; } } </script> |
<template> <div class="container"> <button v-on:click="incrementCount">Increment Count</button> <h4>Total Count: {{count}}</h4> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; @Component export default class AppComponent extends Vue { private count: number = 0; private incrementCount() { this.count++; } } </script>
We can use shorthand @ instead of v-on: like this:
<button @click="incrementCount">Increment</button> |
<button @click="incrementCount">Increment</button>
5.8 Directives
Directives are known as special tokens that enable attaching them as an attribute to all the elements of DOM. All the directives are prefixed by the developers with v-, which stands for VueJS special attribute.
Some of the common Vue directives are described below.
v-text:
<div v-text="count"></div> |
<div v-text="count"></div>
Here, the directive Id is text and the expression is count. This directive updates the text content of div whenever the count property on the Vue instance changes.
v-on: With the use of the v-on directive, the development teams easily call the specific method and listen to the DOM events as they occur.
<button v-on:click="incrementCount">Increment</button> |
<button v-on:click="incrementCount">Increment</button>
V-bind: The directive v-bind allows you to bind the value to a dynamic property on the Vue instance.
<a v-bind:href="url">{{ urlLinkText }}</a> |
<a v-bind:href="url">{{ urlLinkText }}</a>
V-model: This directive allows the VueJs development team to develop a two-way data binding. Besides, VueJS has the capability to change the property of data automatically when there is any change in form field content.
<input v-model="txt" placeholder="Enter text"> <p>Entered Text is: {{ txt }}</p> |
<input v-model="txt" placeholder="Enter text"> <p>Entered Text is: {{ txt }}</p>
V-if: The directive “v-if” is used to conditionally render a block. If the v-if directive returns a true expression, then it can only render a specific block.
<div v-if="showValue">This is v-if directive</div> |
<div v-if="showValue">This is v-if directive</div>
Here, showValue is nothing but a term that is defined in the data of the component.
v-for: To render a list of objects or items, we can use the v-for directive. Generally, v-for is used to iterate on array values.
<ul> <li v-for="product in products" v-bind:key="product">{{ product }}</li> </ul> |
<ul> <li v-for="product in products" v-bind:key="product">{{ product }}</li> </ul>
Here, the v-bind: the key is used to set the properties of each product in the list.
5.9 Rendering
- Conditional Rendering
For conditional rendering of elements in DOM v-if, v-else and v-show directives are used.
Already Visited First Visit |
Already Visited First Visit
Here, if property “is visited” is true then it will add the first h1 to the DOM and the text “Already Visited” gets printed. If “is visited” is false then it will render the second h1 into the DOM and print text “First Visit”.
Directive v-show is used for conditional base render HTML elements. If the condition returns false then the v-show directive only hides the HTML element.
Already Visited |
Already Visited
- List Rendering
v-for directive to render a list of items-based objects and arrays. The VueJS developers can use the v-for directive with the use of the syntax: “user in userList”. Here, the userList means that it is the list of users. And in this model, user is an alias for the array of userList.
<ul> <li v-for="user in userList" :key="user">{{ user }}</li> </ul> |
<ul> <li v-for="user in userList" :key="user">{{ user }}</li> </ul>
5.10 Modifiers
Modifiers are used for binding a directive in a special way.In your application utilize built-in modifiers like Form modifiers, Event Modifiers, Key Modifiers.
- Event modifiers
- .self
- .prevent
- .stop
- .passive
- .once
- .capture
<form v-on:submit.prevent="onSubmit"> ... </form> |
<form v-on:submit.prevent="onSubmit"> ... </form>
- Model modifiers
- .lazy
- .number
- .trim
<input v-model.lazy="data"> |
<input v-model.lazy="data">
5.11 EventBus
An “eventBus” is a Vue instance that can emit an event into the component. It is used to enable isolated components to subscribe and publish custom events between each other. In smaller applications use of “eventBus” is recommended (subscribe and handle broadcasting throughout the entire system).
Example:
Create an EventBus instance within an event-bus.ts file.
import Vue from 'Vue'; //Initialize eventBus instance const eventBus = new Vue(); export default events; |
import Vue from 'Vue'; //Initialize eventBus instance const eventBus = new Vue(); export default events;
Here, Use of EventBus into interface to emit events in ItemComponent.
<template> <div> <input v-model="item" type="number"> <button @click="addItem" class="add-item"> Add New Item </button> </div> </template> <style scoped=""> .add-item{margin: 10px;;} </style> <script lang="ts"> import { Component, Vue } from "Vue-property-decorator"; import eventBus from '../event-bus'; @Component export default class ItemComponent extends Vue { private item: number = 0; private addItem() { eventBus.$emit("item-added", this.item); } } </script> |
<template> <div> <input v-model="item" type="number"> <button @click="addItem" class="add-item"> Add New Item </button> </div> </template> <style scoped=""> .add-item{margin: 10px;;} </style> <script lang="ts"> import { Component, Vue } from "Vue-property-decorator"; import eventBus from '../event-bus'; @Component export default class ItemComponent extends Vue { private item: number = 0; private addItem() { eventBus.$emit("item-added", this.item); } } </script>
Attach the EventBus listener, EventBus.$on, on the created() lifecycle hook of the ItemListComponent. When Item Component emits the event, it is passed a number value within the event object.
<template> <div> <h4>Items: {{ items.join(", ") }}</h4> </div> </template> <script lang="ts"> import { Component, Vue } from "Vue-property-decorator"; import eventBus from '../event-bus'; @Component export default class ItemList extends Vue { private items: number[] = []; private created() { eventBus.$on("item-added", (value: number) => { this.items.push(value); }); } } </script> |
<template> <div> <h4>Items: {{ items.join(", ") }}</h4> </div> </template> <script lang="ts"> import { Component, Vue } from "Vue-property-decorator"; import eventBus from '../event-bus'; @Component export default class ItemList extends Vue { private items: number[] = []; private created() { eventBus.$on("item-added", (value: number) => { this.items.push(value); }); } } </script>
Register both components in the App.Vue component.
<template> <div class="container"> <item></item> <itemlist></itemlist> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; import Item from "@/components/ItemComponent.Vue"; import ItemList from "@/components/ItemListComponent.Vue"; @Component({ components: { Item, ItemList }, }) export default class App extends Vue { } </script> |
<template> <div class="container"> <item></item> <itemlist></itemlist> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; import Item from "@/components/ItemComponent.Vue"; import ItemList from "@/components/ItemListComponent.Vue"; @Component({ components: { Item, ItemList }, }) export default class App extends Vue { } </script>
5.12 State Management (Vuex Store)
The development team uses Vuex as a state management library in every VueJS application they develop. Vuex introduces centralized means manage state features by using below core concepts (Store concept):
- State Tree: It is nothing but an object containing the data which can be set as empty data objects when the state is in its initialization phase.
- Getters: When it comes to accessing data from the Vuex store, the function getters are used.
- Mutations: When you want to perform state modification, the use of mutations is the best option as it can only run synchronous code.
- Actions: To carry out data in-store mutation, developers use Vuex which carries out actions that can easily contain asynchronous activities.
In medium/large-sized applications use “Vuex Store” is recommended.
Example:
import Vue from 'value; //here plugged and use Vuex import Vuex from 'Vuex'; Vue.use(Vuex) const state = { count: 0, }; const mutations = { incrementCount(state) { state.count++; }, }; const actions = { incrementCount: ({ commit }) => commit('incrementCount'), }; const getters = { isValueEvenOrOdd: (state) => state.count % 2 !== 0 ? ‘odd : 'even', }; export default new Vuex.Store({ state, getters, actions, mutations, }); |
import Vue from 'value; //here plugged and use Vuex import Vuex from 'Vuex'; Vue.use(Vuex) const state = { count: 0, }; const mutations = { incrementCount(state) { state.count++; }, }; const actions = { incrementCount: ({ commit }) => commit('incrementCount'), }; const getters = { isValueEvenOrOdd: (state) => state.count % 2 !== 0 ? ‘odd : 'even', }; export default new Vuex.Store({ state, getters, actions, mutations, });
The above example contains state, view, and actions where the state can be changed as per the interaction with the actions.
6. VueJS Guide for Coding Style & Best Practices
Here’s a brief guide to help you follow coding style and best practices in Vue.js.
6.1 Continue Using: Key Inside V-for Directive in Vue App
The use of the “: key” attribute with the “v-for” directive enables the developers to make the business application be predictable and consistent every time they want to manipulate its data. This is important as it enables the VueJS to track the component state of the application and have a constant reference about all the elements of the system. For instance, keys are useful when it comes to using Vue animations or transitions.
And without using keys, Vue has the capability to make DOM efficient whenever possible. So, HTML elements in the v-for appear out of order or their behavior will be less predictable. if each element has a unique reference key, then we have a better prediction of how exactly our Vue app will handle DOM manipulation.
<!-- BAD CODE--> <div v-for='category in categories> </div> <!— GOOD CODE --> <div v-for='category in categories’ :key='category.id'></div |
<!-- BAD CODE--> <div v-for='category in categories> </div> <!— GOOD CODE --> <div v-for='category in categories’ :key='category.id'></div
6.2 Try Using Kebab-Case for Events
When it comes to transmitting from custom events, one of the best things to do is start using kebab-case. The main reason behind this is that the parent Vue component has the same syntax that can be used to listen to that event. Therefore, to have consistency in the Vue components of the system and to have the code that is perfectly readable and accurate, using kebab-case is the ultimate solution.
PopupWindow.Vue this.$emit('close-window') ParentComponent.Vue <popup-window @close-window='handleEvent()' /> |
PopupWindow.Vue this.$emit('close-window') ParentComponent.Vue <popup-window @close-window='handleEvent()' />
6.3 Component Reusability & Communication
- Reusability of Vue components can offer a lot more user flexibility. Try to create a common Vue component with maximum required props to reuse it in all other pages in the whole application. For example, if you create common Vue components for the confirmation messages (you can pass dynamic confirmation message text, button text, icons name, etc.). In a similar manner, one can easily create a common Vue component that can carry out the add/edit operation with the same bindings and model.
- When it comes to data communication between child and Vue components, the use of “event emitter” and “props” is essential. Once created, we can reuse common components across the application by adding required argument props and code in the component.
Example:
In parent component (App.Vue):
<template> <div class="container"> <item :value="value" @onvaluechange="handleData"></item> <h3>Value(emitted from child-component): {{value}}</h3> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; import Item from "@/components/ItemComponent.Vue"; @Component({ components: { Item }, }) export default class App extends Vue { private value: string = "Vue.js Application"; private handleData(data: string) { // get the data after child dealing this.value = data; } } </script> |
<template> <div class="container"> <item :value="value" @onvaluechange="handleData"></item> <h3>Value(emitted from child-component): {{value}}</h3> </div> </template> <style scoped=""> .container{text-align: center;} </style> <script lang="ts"> import { Component, Vue } from 'Vue-property-decorator'; import Item from "@/components/ItemComponent.Vue"; @Component({ components: { Item }, }) export default class App extends Vue { private value: string = "Vue.js Application"; private handleData(data: string) { // get the data after child dealing this.value = data; } } </script>
In Child Component (Item.Vue):
<template> <div> <label>Enter Value: </label><input v-model="localValue" type="text"> <button class="save-btn" @click="submitValue">Save</button> </div> </template> <style scoped=""> .save-btn{margin: 10px;} </style> <script lang="ts"> import { Component, Vue, Prop } from "Vue-property-decorator"; @Component export default class ChildComponent extends Vue { @Prop({default: ""}) private value: string; private localValue: string = ""; private mounted() { this.localValue = this.value // assign value of “value” prop to localValue variable } private submitValue() { this.$emit('onValueChange', this.localValue) // handle data and callback to parent } } </script> |
<template> <div> <label>Enter Value: </label><input v-model="localValue" type="text"> <button class="save-btn" @click="submitValue">Save</button> </div> </template> <style scoped=""> .save-btn{margin: 10px;} </style> <script lang="ts"> import { Component, Vue, Prop } from "Vue-property-decorator"; @Component export default class ChildComponent extends Vue { @Prop({default: ""}) private value: string; private localValue: string = ""; private mounted() { this.localValue = this.value // assign value of “value” prop to localValue variable } private submitValue() { this.$emit('onValueChange', this.localValue) // handle data and callback to parent } } </script>
With the use of “v-model”, one can easily implement a two-way data-binding in tailor-made components without evening using event emitters and props. And for data communication, one can use eventBus, especially when it is for non-relevant components.
6.4 Assigning Data Types
To reduce casting time and other casting problems, use correct data types instead of “any” wherever possible.
Avoid casting inside the loop.
In the case of two different data types used for the same property, then implement type casting for both the types or using the condition.
Example:
const tempVariable: any = 0; [wrong] const tempVariable: number = 0; [Right] |
const tempVariable: any = 0; [wrong] const tempVariable: number = 0; [Right]
6.5 Clean Code and Refactoring
- Use common or shared methods, utilities for reusable code.
- To maintain code transparency and quality use tslint or eslint analysis tools.
Example:
var test: number = 0; “Identifier 'test' is never reassigned; use 'const' instead of 'var'” |
var test: number = 0; “Identifier 'test' is never reassigned; use 'const' instead of 'var'”
6.6 Design
Use the latest version of the Vuetify package to utilize the latest design styles. As per previous experience Vuetify rapidly changes the versions (sometimes with drastic changes in design) so kindly get the latest version at a time of implantation after some interval regularly to avoid big changes at last.
npm update Vuetify |
npm update Vuetify
6.7 Global Variables
Create and keep all the global variables in one (environment.json) file so after the deployment you can update global items without any rebuilds.
6.8 Rapidly Update and Check for the Outdated NPM
Always keep npm packages up-to-date to avoid any dependency errors at the time of deployment.
npm outdated npx npm-check-updates -u npm install |
npm outdated npx npm-check-updates -u npm install
6.9 Initialization of Data
- By turning existing properties into reactive getters and setters, Vue is able to detect data changes. Instead of constructing numerous getters and setters, use the watch property to obtain the most recent and modified values that are dependent on another (Avoid the use of Watch inside an array list of objects).
- Avoid memory leaks – When components are destroyed then remove custom instances, events, intervals after.
6.10 Elements
- Use $refs instead of getting elements by id or class name to reduce the use of JavaScript.
- Avoid using jQuery in favor of typescript because typescript makes our code simple, clean, consistent, and reusable. It also allows for faster code rendering and the detection and correction of additional issues during development.
Example:
const subs = this.$refs.childComponent as ChildComponent; // [Take reference of child component] |
const subs = this.$refs.childComponent as ChildComponent; // [Take reference of child component]
7. Vue JS Performance Optimization
Below listed are some of the performance optimization techniques that we can use in our Vue.js application to make it load faster and improve user experience.
7.1 Use Dynamic Imports for Routes
When building apps with a bundler, the Vue Js app is bundled into one large JavaScript file. Each component is compiled into smaller file pieces, each chunk for a route component, employing lazy loading of routes. As a result, a new chunk is only requested when a user navigates to a new route.
It’s simple to lazy-load route components using Vue’s async component functionality and Webpack’s code splitting capability.
The developer can easily specify an async component as one of the factory functions, that can returns a Promise without any problem:
const UserList = () => Promise.resolve({ /* definition of component */ }) |
const UserList = () => Promise.resolve({ /* definition of component */ })
When it comes to indicating the code-split point, the development team can use dynamic import syntax in webpack 2:
import('./UserList.Vue') // returns a Promise |
import('./UserList.Vue') // returns a Promise
Combination of two,how to define an async component that will be automatically code-split by webpack:
const router = new Router({ routes: [ { path: '/userList', component: UserList } ] }); |
const router = new Router({ routes: [ { path: '/userList', component: UserList } ] });
When the developer registers components with the use of the same pattern, webpack can automatically split every component of the route into a separate piece. Lazy loading on routes improves the actual performance of an application.
7.2 Minimize the Use of External Libraries
- Avoid using third-party libraries if they don’t have much to offer. Because there is an addition to the costs, from the learning curve to maintenance, that wind up being the same as or even more than the cost of developing your solution. If there is a need for a tiny component or piece of code, take the time to create it yourself, as third-party performance concerns are difficult to resolve.
- When looking for a package, make sure to consider your selections among the different possibilities you come across. The most suited package for your project is one that is constructed in a modular style and enables tree-shaking.
7.3 Avoid Placing Redundant Data in the Vuex Storage
Vuex may be useful in some situations, but try to use it only when absolutely necessary. Is this piece of information needed in more than two non-parent-child components?
- This is the question to ask before putting something into Vuex. Store common data in Vuex if data is shared by more than two components, otherwise use local component data.
- This is essential since keeping everything in Vuex adds a layer of complexity to the project and can occasionally cause performance difficulties, such as having large amounts of data in the store that aren’t relevant to many parts of the app.
7.4 Lazy Load Images
If your application has lots of image files, it is recommended to lazy load them. Only the media files that are visible in the view-port are requested on the first-page load; the remainder is requested as the user navigates around the application.
The Vue-lazyload package, which is lightweight and versatile, may be used to load pictures slowly.
7.5 Installation: NPM Install Vue-Lazyload
Setup:
import Vue from "Vue"; import VueLazyload from "Vue-lazyload"; Vue.use(VueLazyload); |
import Vue from "Vue"; import VueLazyload from "Vue-lazyload"; Vue.use(VueLazyload);
v-lazy directive can be used for images instead of the src attribute.
7.6 Code Performance
- Avoid writing complex logic in the watch, computed, update, or beforeUpdate hooks.
- Complicated logic surrounding these Vue.js blocks might result in additional component re-renders or render loops. There are chances of it affecting the overall application performance. Below listed are multiple ways, which we can use to improve the performance of our application:
- While passing data from parent to child, try to transform data in the parent component, so in child component use of watchers can be avoided.
- Parent components should be notified by using the event emitter, rather than mutating props directly.
- Instead of setting data inside computed, the use of watchers is recommended.
- When it comes to updating certain data, especially when another part of the data is changed, replace code with the watcher.
7.7 Develop Content in Advance
You may use the “beforeRouteEnter” hook to obtain data when one of your App’s pages needs to display a lot of material based on certain data.
- Data retrieved in the mounted hook.
private userList = []; private async getData() { // get user list } private mounted() { let res: any = await this.getData(); if (res) { this.userList = res.data; } } |
private userList = []; private async getData() { // get user list } private mounted() { let res: any = await this.getData(); if (res) { this.userList = res.data; } }
- Retrieving data in beforeRouteEnter hook:
private userList = []; private async getData() { // get user list } async beforeRouteEnter(to, from, next) { let res: any = await this.getData(); if (res) { this.userList = res.data; } }; |
private userList = []; private async getData() { // get user list } async beforeRouteEnter(to, from, next) { let res: any = await this.getData(); if (res) { this.userList = res.data; } };
- As we can see that the difference in code is not that big, but the latter one has a different visual impact.
8. Vue JS Application Security
When developing an application, we’re majorly focused on performance, SEO, and UI/UX, so the security of the application is often overlooked. There are countless harmful assaults that may be launched from a front end, including the following:
- Uploading of files is unrestricted.
- Clickjacking
- SQL injection XSS attack
- A denial-of-service attack is a type of cyber-attack that prevents a website from (DoS attack)
- A man-in-the-middle assault, also known as a session hijacking, is a kind
Here are some of the common best practices to always keep in mind while developing web applications.
8.1 Enable XSS Protection Mode
If you want to instruct the web browser to block response when the attackers add malicious code, the supply “X-XSS-Protection: 1; mode=block”.
XSS protection mode is enabled by default in most current browsers, although the X-XSS-Protection header should still be included. With this, the older web browsers that aren’t supporting CSP headers can get the benefit of improved security measures.
8.2 Avoid Typical XSS Mistakes
DOM API’s innerHTML can trace the XSS attack. For instance:
document.querySelector('.application').innerHTML = value; |
document.querySelector('.application').innerHTML = value;
This line may be used by an attacker to introduce malicious code. Use textContent instead of innerHTML as much as feasible and don’t set the innerHTML value based on user input.
With the use of the above line, any attacker can add malicious code to the system. Use textContent instead of innerHTML if possible to set the innerHTML value-based on user input.
8.3 Use Captcha
The captcha should be used on public-facing endpoints like registration, login, and contact. A Captcha is computer software or system that can assist prevent DoS (Distributed Denial of Service) attacks by distinguishing people from bots.
8.4. Dependencies in the Audit Regularly
Checking if installed npm packages have been updated to the current version is called auditing dependency packages.
To audit packages, run npm audit commands on a regular basis. This tool displays all obsolete and vulnerable package versions and advises updating to the most recent version.
8.5 Use of Third-party Packages
The usage of third-party libraries may pose security issues, as hackers are increasingly targeting weak points in open source libraries. When choosing a package to integrate with an application, the developer should consider whether the library is open source or not. Also, if there is a lack of transparency, it will result in security risks. And if the library is well-documented, and fulfills particular requirements, and so it is given full support.
9. Conclusion
In this exclusive blog, we have tried to cover all the aspects regarding Vuejs development. With the images, we have shown in each case and features responsible for Vuejs development. We hope this blog Vue JS – Beginner Guide will improve your knowledge about Vue JS and help you easily implement it in the development.
Vishal Shah
Vishal Shah has an extensive understanding of multiple application development frameworks and holds an upper hand with newer trends in order to strive and thrive in the dynamic market. He has nurtured his managerial growth in both technical and business aspects and gives his expertise through his blog posts.
Subscribe to our Newsletter
Signup for our newsletter and join 2700+ global business executives and technology experts to receive handpicked industry insights and latest news
Build your Team
Want to Hire Skilled Developers?
Comments
Leave a message...