; Vue.js- Ideal for applications and information systems | Starbug

Vue.js- Ideal for applications and information systems



During the programming of web information systems and mobile applications, one encounters many options for how a project can be created. Whether it’s the different technologies available, their potential limitations, community support, or even the speed of product development. Despite the fact that Vue.js  is not the only technology we use, it is definitely one of our favorites. The immense community support, rapid development, and excellent compatibility are some of the reasons why Vue has become an integral part of our software product development.

What is Vue.js?

Vue is a versatile JavaScript framework for building user interfaces. Its foundation consists of standard web technologies: HTML, CSS, and JavaScript. It enables fast and easy development of user interfaces and gradual scaling, which is why its popularity among front-end developers continues to grow. Today, it boasts a massive community.

Support for Vue.js and the Community

Popular frameworks such as Nuxt, VuePress, Ionic, Quasar, and many others are built on Vue. Due to Vue’s large community, various plugins that streamline development are continuously emerging. The most commonly used plugins are for Vue Router, state management, testing tools, Static-Site-Generation (SSG), and Server-Side-Rendering (SSR). A significant advantage is that Vue also supports TypeScript, which helps us make fewer errors during development.

Connecting HTML Pages and Data

The fundamental building blocks of Vue are components that connect data with the HTML template. This means that when data changes, the HTML template automatically updates as well. In templates, we use specific syntax to link data with HTML. To display a value, we use {{ value }}. Additionally, there are predefined directives that can be applied to HTML elements. For example, these directives can conditionally render an element, render elements in a list, or reactively change attributes like class, src, and any other attributes that are part of the element, including custom-defined ones.

<template>
	<div class="classes">
		<p style="textStyle">Hello, {{ name }}</p>
		<div v-if="condition">Conditionally rendered element</div>
		<ul>
			<li v-for="number in numArray">{{ number }}</li>
		</ul>
	</div>
</template>
<script setup>
  import {reactive, ref } from 'vue'
  const name = ref()
  const condition = ref(false)
  const numArray = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
  const classes = ref(['container', 'bg-dark'])
  const textStyle = reactive({
  })
  color: 'black',
  fontSize: '20px'
</script>
<style>
  .container {
  padding: 0 1rem;
  }
  .bg-dark {
  background: #2c3e50;
  }
</style>                                     
                        

We can certainly agree that achieving the same behavior with Vanilla JavaScript or even with jQuery would require writing significantly more code.

Binding Data with Web Pages

Additionally, Vue allows us to bind a variable with inputs through “two-way binding.” This means that when the data in the variable changes, it is reflected in the input, and when the data in the input changes, the variable’s value is updated as well. This feature makes working with forms and processing user data very simple, such as pre-filling a form when editing existing data.

<template>
  <input type="email" v-model="email">
</template>
<script setup>
  import { ref } from 'vue'
  const email = ref()
</script>                            
                                            
                        

Events in Vue.js

We can just as easily listen to events of HTML elements and Vue components using special syntax. This is often used for handling buttons or forms. When handling native events of HTML elements, we can, for instance, stop event bubbling with @click.stop or prevent the default behavior of an element, such as with a form’s submit event using @submit.prevent. In this way, Vue allows us to work with all native events of HTML elements out-of-the-box.

<template>
  <form @submit.prevent="handleFormSubmit">
    <input type="email" v-model="email">
    <input type="password" v-model="password">
    <CustomInputComponent @custom-event="onCustomComponentEvent" s
    <button type="submit" @click="onButtonClick">Submit</button>
  </form>
</template>
<script setup>
  import { ref } from 'vue'
  import CustomInputComponent from '@/components/CustomInputComponent.vue'
  const email = ref()
  const password = ref()
  const handleFormSubmit = () ⇒ {
  }
  // runs when form emits submit event
  const onButtonClick = () ⇒ {
  }
  // runs when button is clicked
  const onCustomComponentEvent = () ⇒ {
  }
  // runs when our custom component emits customEvent
</script>                              
                        

Reusing Components

Components, like functions, can have input parameters called properties (props). This allows us to create a component that can be used in multiple places within the application without being tied to the same data. For example, we can have a Button component with props such as color, style, size, and so on. We can then use this component in different parts of the application, and if a change is needed, we only have to make it in one place, in the Button component. Whenever its props change, the component re-renders.

<template>
  <div>
    <ButtonComponent size="lg" outline color="primary">
      Primary outline large Button
    </ButtonComponent>
    <ButtonComponent size="sm" color="secondary">
      Secondary small Button
    </ButtonComponent>
    <ButtonComponent
      :size="buttonConfig.size"
      :color="buttonConfig.color"
      :outline="buttonConfig.isOutline"
      Dynamic button
    </ButtonComponent>
  </div>
</template>
<script setup>
  import ButtonComponent from '@/components/ButtonComponent.vue'
  import {reactive } from 'vue'
  const buttonConfig = reactive({
  size: 'sm',
  color: 'primary',
  isOutline: false
  })
</script>                              
                        
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>App</title>
  </head>
  <body>
    <div id="app">
      ← some html→→
      <form-component
      ←!— some html→
    </div>
    <script type="module" src="/path/to/vue.js"></script>
  </body>
</html>                              
                        

How does it actually work?

The current version of Vue, as well as all previous versions, use the Virtual DOM to maintain the state and structure of all components, which is then used to render the actual DOM. The Virtual DOM is a JavaScript representation of the real DOM. Here’s how it works: Vue looks at the template and compiles it into a render function, which returns a Virtual DOM Tree based on the data. This tree is then mounted as the actual DOM and displayed. When reactive data changes, the render function runs again, creating a new Virtual DOM Tree. This new tree is compared with the old one, and any necessary changes are reflected in the actual DOM.

Static elements that are not linked to reactive data do not create additional branches in the Virtual DOM; they are created only once. Vue does not need to compare these elements repeatedly because it knows they will never change.

Currently, there is work being done on a new rendering approach called Vue Vapor, which aims to eliminate the need to compare every node in the Virtual DOM and instead immediately redraw the exact part that has changed.

Using Vue.js in Other Solutions

In addition to using Vue as the framework for an entire project, it can also be integrated into an existing solution. For example, if we have an application that returns complete HTML from the server but we want to add reactivity to a form, we can simply create this form as a Vue component.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>App</title>
  </head>
  <body>
    <div id="app">
      ← some html→→
      <form-component
      ←!— some html→
    </div>
    <script type="module" src="/path/to/vue.js"></script>
  </body>
</html>                                 
                        
In the vue.js file, we then create an instance of Vue, register all the components we will use, and mount it using the mount() function, which takes as a parameter the selector of the element in which all the Vue components must be nested. If we use a class selector and it matches multiple elements, Vue will only mount on the first one. Typically, Vue is mounted on a root element within the body.
import { createApp } from 'vue'
import FormComponent from '@/components/FormComponent.vue'
createApp({})
.component('form-component', FormComponent)
.mount('#app')                             
                        

SSR vs SPA

Vue.js is indeed a versatile framework, suitable for developing Single-Page Applications (SPA) or as an addition to existing solutions. Its capabilities, enhanced by support for Server-Side Rendering (SSR) and Static-Site Generation (SSG), are limited only by our imagination. While some search engines today can index SPAs, it’s important to note that if SEO is a high priority, SSR becomes essential. This is because, in the case of an SPA, the server returns a blank HTML page, and the content is rendered only after the JavaScript is executed.


Martin Jurek CEO