home / blog / Dev Tips

Improve Vue Performance with v-once + v-memo

Rendering performance is a vital metric for frontend developers. For every second your page takes to render, the bounce rate increases.

And when it comes to creating a smooth user experience? Near instantaneous feedback is key to giving people a responsive app experience.

While Vue is already one of the better performing Javascript frameworks out of the box, there are ways that developers can improve the performance of their apps.

There are several ways to optimize the rendering of Vue apps - ranging from virtual scrolling to optimizing your v-for elements.

But one extremely easy way to optimize rendering is by only re-rendering what you need to.

Whenever a component’s data changes, that component and its children will re-render, there are ways to eliminate unnecessary tasks with two lesser-used Vue directives: v-once and v-memo.

Let’s jump right in and see how we can use these in our app.

v-once

The v-once directive renders the element/component once and only once. After the initial render, this element and all of its children will be treated as static content.

This can be great for optimizing render performance in your app.

To use this, all we have to do is add v-once to the element in our template. We don’t even need to add an expression like some of Vue’s other directives.

v-once

vue
<template>
  <p v-once>{{ msg }}</p>
</template>
 

It works with single elements, elements with children, components, v-for directives, anything in your template.

App.vue

vue
<template>
  <!-- single elements -->
  <p v-once>{{ msg }}</p>
  <!-- elements with children -->
  <div v-once>
    <p>{{ notification}}</p>
  </div>
  <!-- components -->
  <my-component v-once />
  <!-- v-for directives -->
  <li v-for="”item" in list” v-once>{{item}}</li>
</template>
 

So let’s say we have this example template with some reactive data, a

with v-memo, and a button that changes the text.

VOnceExample.vue

vue
<script setup>
  import { ref } from "vue";
  const msg = ref("hello world");
</script>
<template>
  <div>
    <p v-once>{{ msg }}</p>
    <button @click="msg = 'changed message'">Change message</button>
    <div>
      Current state:
      <p>msg: {{ msg }}</p>
    </div>
  </div>
</template>
 

When we click our button, we can see that even though the value of msg changes, the paragraph does not change thanks to v-once.

When used with v-if or v-show, once our element is rendered once, the v-if or v-show will no longer apply meaning that if it’s visible on the first render, it will always be visible. And if it’s hidden, it will always be hidden.

VOnceExample.vue

vue
<script setup>
  import { ref } from "vue";

  const msg = ref("hello world");
  const show = ref(false);
</script>

<template>
  <div>
    <p v-once v-if="show">{{ msg }}</p>
    <button @click="show = !show">Toggle</button>
    <button @click="msg = 'changed message'">Change message</button>
    <div>
      Current state:
      <p>msg: {{ msg }}</p>
    </div>
  </div>
</template>
 

When would I use v-once?

You should use v-once if there is no circumstance that you will need to re-render an element. A couple examples could be:

  • Displaying account information in the sidebar

  • Showing article text

  • Persisting the column names in a table

Obviously, there are tons of other examples - but just think about if this works well in your app.

v-memo

The v-memo directive memoizes a sub-tree of a template - meaning that it stores the result of previous renders to speed up future ones.

It accepts a dependency array and will only re-render if one of the values in the array has changed. Basically, we're saying to only update this sub-tree if one of these values changes.

v-memo

vue
<template>
  <p v-memo="[msg]">{{ msg }}</p>
</template>
 

Going on with this logic where changes in the value of our dependencies will trigger an update, passing in an empty dependency array will function the same as using v-once where it will never re-render.

these are the same

vue
<template>
  <p v-once>{{ msg }}</p>
  <p v-memo="[]">{{ msg }}</p>
</template>
 

So let’s look at this example where we have a few different count variables, but our div will only update when subscribers updates.

VMemoExample.vue

vue
<script setup>
  import { ref } from "vue";

  const subscribers = ref(4000);
  const views = ref(10000);
  const likes = ref(3000);
</script>
<template>
  <div>
    <div v-memo="[subscribers]">
      <p>Subscribers: {{subscribers}}</p>
      <p>Views: {{views}}</p>
      <p>Likes: {{likes}}</p>
    </div>
    <button @click="subscribers++">Subscribers++</button>
    <button @click="views++">Views++</button>
    <button @click="likes++">Likes++</button>
    <div>
      <p>Current state:</p>
      <p>Subscribers: {{subscribers}}</p>
      <p>Views: {{views}}</p>
      <p>Likes: {{likes}}</p>
    </div>
  </div>
</template>
 

If we modify the other pieces of component data, our div will not re-render, but as soon as we update the value of subscribers…BAM! There’s the render.

Pretty handy if we need to control exactly when a large component re-renders.

There is one disclaimer in the Vue docs, though.

v-memo does not work inside of a v-for loop, so if we want to memoize something with a v-for, we have to put them on the same element.

According to the v-docs themselves, v-memo will rarely be needed. Its main use case is for micro-optimizations in situations where the performance is vital for your app. Most commonly, v-memo is used when rendering extremely large lists in a v-for.


Latest Posts

Top Tools

Getting Started with Vuex in Vue 3

Vuex is a state-management system following the Flux pattern that lets us create a global store with unidirectional data flow across our Vue 3 app.

Dev Tips +Video

Improve Vue Performance with v-once + v-memo

Rendering performance is a vital metric for frontend developers. Improve your Vue app's performance with these two directives.

Top Tools

Making a Markdown-Based Blog with Vue and Gridsome

Use Vue with Gridsome is one of the easiest ways to create static websites from just Markdown files.

Join 5000+ Vue Developers

Every week we send out exclusive tips, tutorials, and more to thousands of developers on our mailing list. 100% Free.