Marcin Król
Marcin Król

Reputation: 1654

Vue.js poor binding performance

I came across a performance problem that boggles my mind. Given the following component:

<template lang="pug">
div
  div {{ counter }}
  div(v-for="idx in new Array(10000).keys()", :key="idx")
    b-button(v-on:click="increment()") ++
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";

@Component
export default class Test extends Vue {
  private counter = 0;

  increment() {
    console.log(Date.now());
    this.counter++;
  }
}
</script>

I expect that when I change counter vue does not rerender the full component. It seems I am wrong I get horrible performance when counter is changed. Am I missing something, is it how vue is supposed to work?

UPDATE

I replaced the new Array(10000).keys() call with a precomputed value but performance stays the same. Replacing b-button with a regular button improves performance significantly which indicates to me that for some reason all the buttons are recreated every time counter changes.

<template lang="pug">
div
  div {{ counter }}
  div(v-for="idx in keys", :key="idx")
    b-button(v-on:click="increment()") ++
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";

@Component
export default class Test extends Vue {
  private counter = 0;
  private keys = [...new Array(10000).keys()];

  increment() {
    console.log(Date.now());
    this.counter++;
  }
}
</script>

UPDATE

Removing the div {{ counter }} binding gives perfect performance (e.g. replacing with div 0).

Upvotes: 0

Views: 330

Answers (1)

Riyaz Khan
Riyaz Khan

Reputation: 3238

The problem is that you are using a function inside and creating a new instance in the loop and then looping over it, so every time the counter update, that "new Array" again initiate.

UPDATE

The problem is with your "new Array(100).keys()", whenever you update "counter", it re-renders because of that.

And if you use instead of that place, normal array data, it will work and you won't get a re-render issue.

Use computed property:

dataArrayKey () {
            return [...new Array(10000).keys()]
          }

And then in the loop, use the computed property array, like this:

<template lang="pug">
div
  div {{ counter }}
  div(v-for="idx in dataArrayKey", :key="idx")
    b-button(v-on:click="increment()", :key="idx + '-button'") ++
</template>

Upvotes: 1

Related Questions