Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cleanest way to re-render component in Vue

I have a Keyboard.vue component containing many Key.vue child component instances (one for each key).

In Key.vue, the key is actually a html <button> element that can get disabled.

By clicking a certain button in my app, I want to reset keyboard and make all keys enabled again. I thought that setting a v-if to false then to true again (<keyboard v-if="BooleanValue" />) would re-render Keyboard.vue and all its Key.vue child component instances.

It doesn't. Why not?

App.vue

<template>
  <div class="app">
    ...
    <keyboard v-if="!gameIsOver && showKeyboard" />
    ...
  </div>
</template>

<script>
export default {
  components: {
    Keyboard
  },
  computed: {
    gameIsOver () {
      return this.$store.state.gameIsOver
    },
    showKeyboard () {
      return this.$store.state.showKeyboard
    }
  }

Keyboard.vue

<template>
  <section>
    <key class="letter" v-for="(letter) in letters" :key="letter" :letter="letter" />
  </section>
</template>

Key.vue

<template>
  <button :disabled="disabled" @click="checkLetter(letter)">
    {{ letter }}
  </button>
</template>

<script>
export default {
  ...
  data () {
    return {
      disabled: false
    }
  }

My button resetting keyboard triggers:

this.$store.commit('SET_KEYBOARD_VISIBILITY', false)
this.$store.commit('SET_KEYBOARD_VISIBILITY', true)
like image 430
drake035 Avatar asked Oct 30 '25 12:10

drake035


1 Answers

To answer your question first, the cleanest way to re-render a Vue component or any element is to bind it's key attribute to something reactive that will control the re-renders, whenever the key value changes it will trigger a re-render.

To make such a unique key per render, I would probably use an incremented number and whenever I would like to re-render I would increment it.

<template>
<div>
  <div :key="renderKey">
  </div>
</div>
</template.

<script>
export default {
  data: () => ({
    renderKey: 0
  }),
  methods: {
    reRender() {
       this.renderKey++;
    }
  }
};
</script>

Now as for why toggling v-if didn't work: Toggling a reactive property between true and false doesn't necessarily trigger 2 re-renders because Vue has an async update queue which applies DOM changes in patches in certain time frames, not per individual update. This why Vue is so fast and efficient.

So you trigger disabled to false, then to true. The renderer will decide not to update the DOM because the final value has not changed from the last time, the timing is about 16ms If I recall correctly. So you could make that work by waiting more than 16ms between toggling your prop between true and false, I say "could" but not "should".

like image 114
logaretm Avatar answered Nov 01 '25 07:11

logaretm