Correct Method of Forcing Component Re rendering in Vue

  • 2021-10-16 00:48:03
  • OfStack

Sometimes it is not enough to rely on the vue response to update the data. Instead, we need to manually re-render the component to update the data. Or, we may just want to abandon the current DOM and start over. So, how can vue re-render components in the right way?

The best way to force Vue to re-render a component is to set key on the component. When we need to re-render the component, just change the value of key, and Vue will re-render the component.

This is a very simple solution.

Of course, you may be more interested in other ways:

Simple and rude way: reload the whole page Improper way: use v-if Better method: use the built-in forceUpdate method of Vue Best way: Make key changes on components

Simple and rude way: reload the whole page

This is equivalent to restarting your computer every time you want to shut down the application.

This may be useful, but this is a very bad solution. Don't do this. Let's look at a better way.

Improper way: use v-if

The v-if directive, which is rendered only when the component is true. If it is false, the component does not exist in DOM.

Let's see how v-if works. In template, add the v-if instruction:


<template>
 <my-component v-if="renderComponent" />
</template>

In script, the method of nextTick is used


<script>
 export default {
  data() {
   return {
    renderComponent: true,
   };
  },
  methods: {
   forceRerender() {
    //  From  DOM  Delete in  my-component  Component 
    this.renderComponent = false;
    
    this.$nextTick(() => {
     //  In  DOM  Add to  my-component  Component 
     this.renderComponent = true;
    });
   }
  }
 };
</script>

The above process is roughly as follows:

Initially renderComponent is set to true, so the my-component component is rendered When we call forceRerender, we immediately set renderComponent to false We stop rendering my-component because the v-if instruction now evaluates to false Set renderComponent back to true in the nextTick method When the v-if instruction evaluates to true, render my-component again

In this process, there are two important parts

First of all, we must wait until nextTick, otherwise we won't see any changes.

In Vue, one tick is one DOM update cycle. Vue will collect all the updates made in the same 1 tick, and at the end of tick, it will render the contents of DOM based on these updates. If we don't wait for next tick, our update to renderComponent will automatically cancel and nothing will change.

Secondly, when we render the second time, Vue will create a brand-new component. Vue will destroy the first one and create a new one, which means that our new my-component will go through all its lifecycle-created, mounted, and so on-like normal 1.

In addition, nextTick can be used with promise 1:


forceRerender() {
 //  From  DOM  Delete in  my-component  Component 
 this.renderComponent = false;

 this.$nextTick().then(() => {
  this.renderComponent = true;
 });
}

However, this is not a good solution, so let's do what Vue wants us to do

Better method: forceUpdate method

This is one of the two best ways to solve this problem, both of which are officially supported by Vue.

Typically, Vue responds to changes in dependencies by updating views. However, when we call forceUpdate, we can also force updates, even if all dependencies are virtually unchanged.

The following are the biggest mistakes most people make when using this method.

If Vue updates automatically when things change, why do we need to force updates?

The reason is that sometimes the response system of Vue can be confusing. We think that Vue will respond to changes in a property or variable, but this is not the case. In some cases, the response system of Vue can't detect any changes at all.

So like the previous method, if you need this to re-render your component, there may be a better way.

There are two different ways to call forceUpdate on the component instance itself and globally:


//  Global 
import Vue from 'vue';
Vue.forceUpdate();

//  Using component instances 
export default {
 methods: {
  methodThatForcesUpdate() {
   // ...
   this.$forceUpdate();
   // ...
  }
 }
}

Important: This does not update any computed properties, and calling forceUpdate only forces the view to be re-rendered.

Best way: Make key changes on components

In many cases, we need to re-render components.

To do this correctly, we will provide an key attribute so that Vue knows that a specific component is associated with a specific data fragment. If key remains the same, no component is changed, but if key changes, Vue knows that the old component should be deleted and a new one created.

Just what we need!

But first, we need to take a short walk around to understand why key is used in Vue.

Why do we need to use key in Vue

1 Once you understand this 1 point, this is a small 1 step to understand how to force re-rendering in the correct way.

Suppose we want to render a list of components with one or more of the following items:

Have local status Some initialization process, usually in created or mounted hooks Unresponsive DOM operation via jQuery or normal api

If you sort the list or update it in any other way, you need to re-render some parts of the list. However, you do not want to re-render everything in the list, but only the changed content.

To help Vue track what has changed and what has not changed, we provide an key property. The index of the array is used here because the index is not bound to a specific object in the list.


const people = [
 { name: 'Evan', age: 34 },
 { name: 'Sarah', age: 98 },
 { name: 'James', age: 45 },
];
 If we use the index to render it, we will get the following results: 

<ul>
 <li v-for="(person, index) in people" :key="index">
  {{ person.name }} - {{ index }}
 </li>
</ul>

// Outputs
Evan - 0
Sarah - 1
James - 2

If you delete Sarah, you get:


Evan - 0
James - 1

The index associated with James is changed even though James is still James. James will be re-rendered, which is not what we want.

So here, we can use only 1 id as key


const people = [
 { id: 'this-is-an-id', name: 'Evan', age: 34 },
 { id: 'unique-id', name: 'Sarah', age: 98 },
 { id: 'another-unique-id', name: 'James', age: 45 },
];

<ul>
 <li v-for="person in people" :key="person.id">
  {{ person.name }} - {{ person.id }}
 </li>
</ul>

Before we removed Sarah from the list, Vue removed the components of Sarah and James, and then created a new component for James. Now, Vue knows that it can keep these two components for Evan and James, and all it has to do is delete Sarah's.

If we add an person to the list, Vue also knows that it can keep all existing components and only need to create a new component and insert it in the correct location. This is useful when we have more complex components that have their own state, have initialization logic, or do any kind of DOM operation.

So let's take a look at the best way to re-render the component.

Change key to force the component to be re-rendered

Finally, this is the best way to force Vue to re-render components (in my opinion).

We can use this strategy of assigning key to child components, but each time we want to re-render the component, we only need to update the key.

This is a very basic method


<template>
 <component-to-re-render :key="componentKey" />
</template>


export default {
 data() {
  return {
   componentKey: 0,
  };
 },
 methods: {
  forceRerender() {
   this.componentKey += 1; 
  }
 }
}

Our componentKey changes every time forceRerender is called. When this happens, Vue will know that it must destroy the component and create a new one. What we get is a subcomponent, which will reinitialize itself and "reset" its state.

If you do need to re-render something, select key to change the method instead of the other method.

The above is the Vue forced component re-rendering of the correct method of details, more about vue forced component rendering information please pay attention to other related articles on this site!


Related articles: