Set a variable inside a v-for loop on Vue JS

ryangus picture ryangus · Jul 17, 2018 · Viewed 17.1k times · Source

I have a v-for loop with vue.js on a SPA and I wonder if it's posible to set a variable at the beginning and then just print it everytime you need it, because right now i'm calling a method everytime i need to print the variable.

This is the JSON data.

{
"likes": ["famiglia", "ridere", "caffè", "cioccolato", "tres leches", "ballare", "cinema"],
"dislikes":["tristezze", "abuso su animali", "ingiustizie", "bugie"]

}

Then I use it in a loop:

<template>
<div class="c-interests__item" v-for="(value, key) in interests" :key="key" :data-key="key" :data-is="getEmotion(key)" >

// NOTE: I need to use the variable like this in different places, and I find myself calling getEmotion(key) everythime, is this the way to go on Vue? or there is another way to set a var and just call it where we need it?

<div :class="['c-card__frontTopBox', 'c-card__frontTopBox--' + getEmotion(key)]" ...
<svgicon :icon="getEmotion(key) ...

</div>
</template>

<script>
import interests from '../assets/json/interests.json'
... More imports

let emotion = ''

export default {
  name: 'CInfographicsInterests',
  components: {
    JSubtitle, svgicon
  },
  data () {
    return {
      interests,
      emotion
    }
  },
  methods: {
    getEmotion (key) {
      let emotion = (key === 0) ? 'happy' : 'sad'
      return emotion
    }
  }
}
</script>

// Not relevanty to the question
<style lang='scss'>
.c-interests{...}
</style>
  1. I tried adding a prop like :testy="getEmotion(key)" and then { testy } with no luck...

  2. I tried printing { emotion } directly and it doesn't work

So, there is anyway to acomplish this or should i stick calling the method every time?

Thanks in advance for any help.

Answer

Daniel picture Daniel · Jul 17, 2018

It's not a good idea to use methods inside a template for non-user-directed actions (like onClicks). It's especially bad, when it comes to performance, inside loops.

Instead of using a method, you can use a computed variable to store the state like so

computed: {
  emotions() {
    return this.interests.map((index, key) => key === 0 ? 'happy' : 'sad');
  }
}

This will create an array that will return the data you need, so you can use

<div class="c-interests__item"
    v-for="(value, key) in interests"
    :key="key" />`

which will reduce the amount of times the item gets re-drawn.