window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster already exists') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Vue.js app improvement. Some practical tips - The Codest
The Codest
  • About us
  • Services
    • Software Development
      • Frontend Development
      • Backend Development
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Data Engineers
      • Cloud Engineers
      • QA Engineers
      • Other
    • It Advisory
      • Audit & Consulting
  • Industries
    • Fintech & Banking
    • E-commerce
    • Adtech
    • Healthtech
    • Manufacturing
    • Logistics
    • Automotive
    • IOT
  • Value for
    • CEO
    • CTO
    • Delivery Manager
  • Our team
  • Case Studies
  • Know How
    • Blog
    • Meetups
    • Webinars
    • Resources
Careers Get in touch
  • About us
  • Services
    • Software Development
      • Frontend Development
      • Backend Development
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Data Engineers
      • Cloud Engineers
      • QA Engineers
      • Other
    • It Advisory
      • Audit & Consulting
  • Value for
    • CEO
    • CTO
    • Delivery Manager
  • Our team
  • Case Studies
  • Know How
    • Blog
    • Meetups
    • Webinars
    • Resources
Careers Get in touch
Back arrow GO BACK
2020-10-30
Software Development

Vue.js app improvement. Some practical tips

The Codest

Dominik Grzedzielski

Senior Software Engineer

Vue is a rapidly growing progressive framework for building user interfaces. It became the JavaScript framework with the most stars on GitHub and the most highly starred project of 2016 and 2017 on in the same portal.

Creating applications in Vue is really simple as such, but if you want to build good quality applications, you’re up for a bit more of a challenge.

Being a part of The Codest team and real advocate of Vue technology, I want to share some tips (not copied from official Vue docs) which will effortlessly improve code quality and the performance of Vue applications.

First off, apply the Vue Style Guide and ESLint

I don’t want to repeat what has already been said. There’s a style guide in Vue docs:
Vue 2 docs – style guide or
Vue 3 docs – style guide

You can find there four Rule categories. We really care about three of them:

  • Essential rules preventing us from errors,
  • Recommended and strongly recommended rules for keeping best practices – to improve quality and readability of code.

You may think… “What?! Do I have to remember every rule?” Of course you don’t. You can use ESLint to take care of those rules for you. You just have to set everything properly in the ESLint configuration file. I suggest using the recommended preset as you get a totally free set of rules that help you in building apps with good practices. How to set it up?

By default, you should find extends key in ESLint config and replace "plugin:vue/essential" with "plugin:vue/recommended", that’s all.

Of course, there’s a few rules you should remember, because ESLint cannot handle everything on its own. For example:

  • consistent naming,
  • events naming in kebab-case,
  • prefixing $_namespace_ private properties in plugins, mixins, etc.,
  • single file component top level element order.

Don’t use multiple v-if

It may sometimes be necessary to render conditionally more than 1 element, but people often write something like that:

content

content

content

It’s unnecessary because we can write it more elegantly:

 <template v-if="condition">
   <div>content</div>
   <div>content</div>
   <div>content</div>
 </template>

But what if we want to do it as a root element? In Vue, we can’t use <template> for this purpose. In some cases, wrapping in div could be enough.

That’s ok, but, as much as we may want, sometimes we can’t wrap elements in div, for example, because of html semantic (e.g. <li> has to be a direct child of <ul> or <ol>). So when we have to write:

 <li
   v-for="item in items"
   :key="item.id"
 >
   (( item.name ))
 </li>

…and we’ll see an error like that :

Vue js code

We can deal with it by using JSX and a functional component, also we should pass a boolean and it will replace the v-if.

</>

Don’t write api call handlers in components

Actually, this is only one of the examples of what you shouldn’t do in components. Simply do what is locally necessary in components logic. Every method that could be external should be separated and only called in components e.g. business logic.

Example:

Instead of a method like this:

created() (
this.fetchArticles();
),
methods: (
 async fetchArticles() (
  try (
    const data = await axios.get(url);
    this.articles = data.articles;
    ) catch (e) (
    // handle error
    )
  )
)

Write something like this – just call the proper method that will return API results:

 async fetchArticles() (
   try (
     this.articles = await ArticlesService.fetchAll();
   ) catch (e) (
     // handle error
   )
  )

Use slots instead of large amounts of props

Sometimes using props is just enough, but there are also cases when they are not efficient. It may happen in situations where we would have to add too many props to make the component work like we want it to. The simplest example could be a button component. Without any doubt, it’s a component which could be used anywhere in an application. So, let’s consider a button component like this one.


(( text ))
</>

At this stage, it’s a simple component which accepts only text prop. Ok, but it may not be enough as we will need icons in the button. In this case, we have to add another 2 props (2, because we want to have the option to add before or after text). So, the component will look like this:


(( text ))
</>

It’s not bad, we have only 3 props, but…

What if we need a loading indicator? Well, we would have to add another prop. And that’s for every new feature! Does keeping up with the growth of the number of components sound challenging now? Yes, it does, definitely!

Let’s use slots instead.

Simpler, right? Ok, but how can we get the add icon feature? It’s really easy! Just use the component like this:

Back

Next

Easy way to improve performance

I will share with you some tips that are really easy to implement, so you can instantly benefit.

Lazy load routes

Sometimes we would have routes are available only for admins, or user with particular access, they may also be visited less than others. They are perfect cases for using the lazy load route.

Just use the arrow function in your component property to return import function:

 export default new VueRouter (
   (
     mode: 'history',
     routes: [
       (
         path: '/landing',
         component: () => import('../pages/p-welcome'),
         name: 'welcome'
       ),
  …

Instead of:

import PWelcome from '@/pages/p-welcome';

export default new VueRouter (
(
mode: 'history',
routes: [
(
path: '/landing',
component: PWelcome, //just imported component
name: 'welcome'
),

Lazy loading Vue components

A similar situation may happen with Vue components. We can lazily import single file components like this:

const lazyComponent = () => import('pathToComponent.vue')
export default (
components: (lazyComponent )
)

// Another syntax
export default (
components: (
lazyComponent: () => import('pathToComponent.vue')
)
)

Thanks to the lazy load of that component, it will be downloaded only when  requested. For example, if we have a component with v-if, it will be requested only if the component is to render. So unless the v-if value is true, the component will not be loaded. That’s why lazy importing can be also used for JavaScript files.

Bonus: When using Vue CLI 3+, every lazily loaded resource is prefetched by default!

vue js development

Use transparent wrappers instead of attribute props

Consider a component like this one:

 <template>
   <input
     :value="value"
     class="base-input"
     @input="$emit('input', $event.target.value)"
   >
 </template>

Without any problems, we can use it like this:

or


It works, because Vue allows you to pass html attributes to the component, even if you didn’t declare them as props. The html attributes are applied to the component’s root element (input, in this case).

The problem appears when we want to expand our input component, since it could look like this:

 <template>
   <div class="form-group">
     <label :for="id">(( label ))</label>
     <input
       :id="id"
       :value="value"
       class="base-input"
       @input="$emit('input', $event.target.value)"
     >
   </div>
 </template>

Now, using the component this way:

 <base-input
   v-model="text"
   type="text"
   placeholder="Write something"
 />

will not work like we want, because the type and the placeholder will be applied to div (root element) and that’s make no sense. So, we need to deal with it, because we want to add our attributes to the input element. Your first thought may be “let’s add the props we need!” and of course that will work, but… what if we want to use type, autocomplete, placeholder, autofocus, disabled, inputmode, etc., then we have to define the props for every html attribute. I personally don’t like this lengthy method, so  let’s look for something better!

We can deal with the whole problem in just two lines.

<template>
  <div class="form-group">
    <label :for="id">(( label ))</label>
    <!-- pay attention to v-bind="$attrs" -->
    <input
      :id="id"
      v-bind="$attrs"
      :value="value"
      class="base-input"
      @input="$emit('input', $event.target.value)"
    >
  </div>
</template>

<script>
export default (
  name: 'BaseInput',
  inheritAttrs: false, // <- pay attention to this line
  props: ['value', 'label', 'id']
);
</script>

We can use v-bind="$attrs" and pass attributes directly to <input> without declaring huge amounts of props. Also, remember about adding the option inheritAttrs: false to disable passing the attributes to the root element. Let’s go a bit further: what if we need to add event listeners to this input? Again, it could be handled by props or custom events, but there’s a better solution.

<template>
  <div class="form-group">
    <label :for="id">(( label ))</label>
    <!-- pay attention to v-on="listeners" -->
    <input
      :id="id"
      v-bind="$attrs"
      :value="value"
      class="base-input"
      v-on="listeners"
    >
</div>
</template>

<script>
export default (
  name: 'BaseInput',
  inheritAttrs: false,
  props: ['value', 'label', 'id'],
  computed: (
    listeners() (
      return (
        ...this.$listeners,
        input: event => this.$emit('input', event.target.value)
      );
    )
  )
);
</script>

There’s a new computed property that returns the component for listeners and adds the input listener. We use that computed input by simply writing v-on="listeners".

Use watcher with the immediate option instead of the created hook and watcher together

We often fetch some data on a created (or mounted) hook, but then we need fetch that data with every change of a property, e.g., current page of pagination. Some tend to write it down like this:

<script>
export default (
  name: 'SomeComponent',
  watch: (
    someWatchedProperty() (
      this.fetchData();
    )
  ),
  created() (
    this.fetchData();
  ),
  methods: (
    fetchData() (
      // handle fetch data
    )
  )
);
</script>

Of course, it works, but… It’s not the best approach, not even a good one. So, let’s check how we can refactor this, An example of not so bad approach:

<script>
export default (
name: 'SomeComponent',
watch: (
  someWatchedProperty: 'fetchData'
),
  created() (
    this.fetchData();
  ),
  methods: (
    fetchData() (
      // handle fetch data
    )
  )
);
</script>

The above version is better because another method is not necessary, we only named a method that should be called on to change watchedProperty.

An even better approach:

<script>
  export default (
    name: 'SomeComponent',
    watch: (
      someWatchedProperty: (
        handler: 'fetchData',
        immediate: true
      )
    ),
    methods: (
      fetchData() (
        // handle fetch data
      )
    )
  );
</script>

We got rid of the created hook. By adding the option ‘immediate,’ we make that component call on the fetchData method immediately after the start of the observation (it’s a bit before the created hook and after beforeCreated), so it can be used instead of the created hook.

Vue.js tips summary

These tips will not make your application perfect but using them will quickly improve the quality of your code. Also, I hope you will find something of interest in the above examples.

Note that some of them were simplified for the article’s purposes.

Read more:

JavaScript Is Totally Dead. Some Dude on the Internet

A Deeper Look at the Most Popular React Hooks

Software Projects Where You Can Use JavaScript

Related articles

Software Development

Build Future-Proof Web Apps: Insights from The Codest’s Expert Team

Discover how The Codest excels in creating scalable, interactive web applications with cutting-edge technologies, delivering seamless user experiences across all platforms. Learn how our expertise drives digital transformation and business...

THECODEST
Software Development

Top 10 Latvia-Based Software Development Companies

Learn about Latvia's top software development companies and their innovative solutions in our latest article. Discover how these tech leaders can help elevate your business.

thecodest
Enterprise & Scaleups Solutions

Java Software Development Essentials: A Guide to Outsourcing Successfully

Explore this essential guide on successfully outsourcing Java software development to enhance efficiency, access expertise, and drive project success with The Codest.

thecodest
Software Development

The Ultimate Guide to Outsourcing in Poland

The surge in outsourcing in Poland is driven by economic, educational, and technological advancements, fostering IT growth and a business-friendly climate.

TheCodest
Enterprise & Scaleups Solutions

The Complete Guide to IT Audit Tools and Techniques

IT audits ensure secure, efficient, and compliant systems. Learn more about their importance by reading the full article.

The Codest
Jakub Jakubowicz CTO & Co-Founder

Subscribe to our knowledge base and stay up to date on the expertise from the IT sector.

    About us

    The Codest – International software development company with tech hubs in Poland.

    United Kingdom - Headquarters

    • Office 303B, 182-184 High Street North E6 2JA
      London, England

    Poland - Local Tech Hubs

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Warsaw, Poland

      The Codest

    • Home
    • About us
    • Services
    • Case Studies
    • Know How
    • Careers
    • Dictionary

      Services

    • It Advisory
    • Software Development
    • Backend Development
    • Frontend Development
    • Staff Augmentation
    • Backend Developers
    • Cloud Engineers
    • Data Engineers
    • Other
    • QA Engineers

      Resources

    • Facts and Myths about Cooperating with External Software Development Partner
    • From the USA to Europe: Why do American startups decide to relocate to Europe
    • Tech Offshore Development Hubs Comparison: Tech Offshore Europe (Poland), ASEAN (Philippines), Eurasia (Turkey)
    • What are the top CTOs and CIOs Challenges?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Copyright © 2025 by The Codest. All rights reserved.

    en_USEnglish
    de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek en_USEnglish