Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to make a loop to create objects in Vue3?

Tags:

vue.js

vuejs3

<template>
  <div class="container">
    <div class="gameboard">
      <div v-for="item in boardfields" :key="item.number">
        {{ item.number }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},

  data() {
    return {
      boardfields: [
        { number: 1, isclicked: false },
        { number: 2, isclicked: false },
        { number: 3, isclicked: false },
        { number: 4, isclicked: false },
        { number: 5, isclicked: false },
        { number: 6, isclicked: false },
      ],
    };
  },

As you can see I have a few similar objects in the 'boardfields' array. I have to make around 50 of those. Is there a way to create a loop that creates a certain amount of this object with a different number and pushing it to the array so I don't have to copy and paste it and manually change the numbers?

I think in JS it would be something like

var i;
for (var i = 0, i > 50, i++){
  this.boardfields.push({number: i, isclicked: false});
}
like image 476
Pazulay Avatar asked Jan 27 '21 19:01

Pazulay


People also ask

What is the use of V for in VUE JS?

v-for directive is a Vue. js directive used to loop over a data usually an array or object. First, we will create a div element with id as app and let's apply the v-for directive to an element with data. Now we will create this data by initializing a Vue instance with the data attribute containing the value.


1 Answers

I think @Boussadjra's answer is correct, but wanted to add some context.

The functional [...Array(50)].map()...etc is the popular way to go these days. You can populate the value on data definition or onmount or oncreate, there are some nuances that might be worthwhile considering.

Note that if you are using:

const initialBoard = []
for (var i = 1; i <= 50; i++) {
  initialBoard.push({number: i, isclicked: false});
}

export default {
  name: "App",
  components: {},

  data() {
    return {
      boardfields: initialBoard
    };
  },
}

The value of initialBoard is persistent. The objects are created on first run and are populating the array which is re-used. That means if you create two components, they may share the values of the objects inside the array. IMHO, this is a a side effect you want to avoid unless you explicitly looking for that functionality, even if you only use one instance of the component.

B's solution...

export default {
  name: "App",
  components: {},

  data() {
    return {
      boardfields: [],
    };
  },
  mounted() {
    this.boardFields=[...Array(50)].map((_,i)=>({number: i+1, isclicked: false}))
  }
}

Is safer in that regard, since it generates a new array with new objects every time it is mounted. My preference would be to use created, because it will make the data available on the first draw, but because the variable is preset to an empty array, it's not going to cause errors (like an error in your template if the variable had .length on undifined or null)

Here is an example that illustrates the difference. Not that when the component is remounted or recreated (doesn't make a difference which on here) the data is lost, but the (top) two components don't share the data., wheras the bottom two do.

const app = Vue.createApp({
  data: function() {
    return {
      cKey: 1
    }
  }
})

const prepArr = [...Array(5)].map((_, i) => ({
  name: 'item-' + i
}))

app.component("my-component", {
  data: function() {
    return {
      myArr: []
    }
  },
  created: function() {
    this.myArr = [...Array(5)].map((_, i) => ({
      name: 'item-' + i
    }))
  },
  template: `<div class="h">Component Using created<ul>
    <li v-for="item in myArr">{{ item.name }} <button  @click="()=>{item.name = item.name +'!'}">+</button></li>
  </ul></div>`
});


app.component("persistent-component", {
  data: function() {
    return {
      myArr: prepArr
    }
  },
  template: `<div class="h">Component using persistent<ul>
    <li v-for="item in myArr">{{ item.name }} <button  @click="()=>{item.name = item.name +'!'}">+</button></li>
  </ul></div>`
});


app.mount('#app')
.h{display: inline-block; width: 49%;}
<script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>

<div id="app">
  <div><button @click="()=>{cKey++}">regenerate</button></div>
  <my-component :key="cKey"></my-component>
  <my-component :key="cKey"></my-component>
  <persistent-component :key="cKey"></persistent-component>
  <persistent-component :key="cKey"></persistent-component>
</div>
like image 121
Daniel Avatar answered Nov 15 '22 05:11

Daniel