0

I've got array as below:

return {
   items: [
      { active: false, text: 'text1', textOutput: ''},
      { active: false, text: 'text1', textOutput: ''},
      { active: false, text: 'text1', textOutput: ''},
      ...
   ],
}

now, the purpose of this array is to output data to the DOM, using computed property as below.

I want to output only the data where active: true, which is changing onclick in other part of the web, so computed resultDOM is watching for this change and changing only items.active="true". Also I use text-fields to change items.text[i] values.

computed: {
 resultDOM () {
        for (var i=0; i<this.items.length; i++) {
          if (this.items[i].active) {
            this.items[i].textOutput = '<li>' + this.items[i].text + '</li>'
            console.log('bam')
          }
          else {
            this.items[i].textOutput = ''
            console.log('bam else')
          }          
        }
        var output=''
        for (var i=0; i<this.items.length; i++) {
          output = output + this.items[i].textOutput
        }
        return output
 }
}

The problem is that this takes some time to execute and every time I change only one active to true (or items.text value) computed is doing check on every element of the table, so it's very ineffective. Can I ask you for tips, how should I improve my code to be more efficient? What is the right way to do it?

edit:

<div  v-html="resultDOM"></div>
8
  • can you provide a template for the component? I guess you could use conditional rendering. Commented Feb 26, 2018 at 12:51
  • @oniondomes I added to question. I could use it, but I also need textOutput values for future use (save it to database/other components) Commented Feb 26, 2018 at 12:54
  • I saw you comment too late. I will revise my answer. Commented Feb 26, 2018 at 13:00
  • @oniondomes that's ok, your answer seems correct, the main idea to stick to computed is that I will use it in the future to dynamically change elements of page like <li> objects inside computed and to get the reusable finished HTML this way in many variants Commented Feb 26, 2018 at 13:04
  • 1
    you can at least not iterate through the array twice. put output = output + this.items[i].textOutput inside the first loop. Commented Feb 26, 2018 at 13:27

1 Answer 1

2

You can avoid using computed at all if you take advantage of conditional rendering and v-for directive:

const app = new Vue({
  el: "#app",
  data: {
    items: [
      { active: true, text: 'text1',},
      { active: true, text: 'text2',},
      { active: false, text: 'text3',},
    ],
  },
})
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <ul>
    <li v-for="item in items" v-if="item.active" v-text="item.text"></li>
  </ul>
</div>

jsfiddle

Sign up to request clarification or add additional context in comments.

7 Comments

Good, don't forget the :key attribute when you are using v-for ;) vuejs.org/v2/guide/list.html#key
@thomas-brodusch, one should indeed use v-key when it's possible, but the sample data doesn't really provide any unique values to be keys.
You are right, but you can totally formate a key like this: :key="'itemKey_${index}'" with index from v-for="item, index in item to make a custom unique key if no unique value is provided.
@thomas-brodusch I thought about this, but won't index get changed every time you delete anything from the array? It kinda defeats the purpose of :key.
Of course if the items array get changed, the index will also by updated. Using :key="'itemKey_${index}'" is a tweak to prevent any VueJS's error to be thrown about a missing :key parameter if you haven't pass it one. It also provide you to unique-ify each item when you have to render out multiple list-based components in the same context. There is a great topic about it here forum.vuejs.org/t/v-for-with-simple-arrays-what-key-to-use/…
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.