简体   繁体   中英

vuejs using computed property for array elements

I've got basic template that is outputing text from wysiwyg editor via two-ways data binding as below:

<template>
  <div>
    <quill-editor 
      v-model="debounceText"
      :options="editorOptionProTemplate"
      >
    </quill-editor>
  <div  v-html="textComputed"></div>
  </div>
</template>

<script>
data () {
  return {
    text: ''
  }
},
computed: {
debounceText: {
  get() { return this.text; },
  set: _.debounce(function(newValue) {
    this.text = newValue;
  }, 100)
 },
//using computed for many variants for styling output in web (here just adding <b> tag)
  textComputed() {
    return '<b>' + this.text + '</b>'
  }
 }
</script>

at this level all works fine

Now, I'm changing variable into array (object), using v-for (many elemnents to edit at the same time and outputing them in the array as below):

<template>
  <div v-for="item in items">
    <quill-editor 
      v-model="item.text"
      :options="editorOptionProTemplate"
      >
    </quill-editor>
  <div v-html="textComputedArray"></div>
  </div>
</template>

<script>
data () {
  return {
    items: [
      {active: true, text: 'text1', textOutput: ''},
      {active: true, text: 'text2', textOutput: ''},
      {active: true, text: 'text3', textOutput: ''},
      {active: true, text: 'text4', textOutput: ''},
      {active: true, text: 'text5', textOutput: ''}
   ]
  }
},

textComputedArray: {
        var output=''
          for (var i=0; i<this.items.length; i++) {
            if (this.items[i].active) {
              this.items[i].textOutput= this.items[i].text + '<br />'
              output = output + this.items[i].textOutput
            }
            else {
              this.items[i].textOutput= ''
            }          
          }
          return output
        },
</script>

how should I modify my code to apply debounceText computed to this output? I think that I simply cannot add computed to my template, and also I cannot pass any parameter into computed property.

Maybe someone more experienced than me will give me some solution/advice?

Any time you have an array and you think each item needs a computed, you should look at making a component. That is how data and computeds get attached to each other.

In a lot of cases, you can make a computed based on the array, and it's fine, but you should be aware that any change to the array causes a recompute of the entire computed array. With a component, only the affected rows are recomputed. A simple example is embedded here.

 new Vue({ el: '#app', data: { arr: [1, 2, 3] }, computed: { carr() { console.log("Computing the whole array"); return this.arr.map(x => 'hi ' + x); } }, components: { addHi: { props: ['value'], template: '<div>{{a}}</div>', computed: { a() { console.log("Computing for", this.value); return 'hi ' + this.value; } } } }, created() { setTimeout(() => { console.log("** Changing a value"); this.arr.splice(2, 1, 'X'); }, 1500); } }); 
 <script src="//unpkg.com/vue@latest/dist/vue.js"></script> <div id="app"> <div v-for="a in carr">{{a}}</div> <add-hi v-for="a in arr" :value="a" :key="a"></add-hi> </div> 

If you need your computed to be writable, you won't be able to edit individual items, so you're really forced to make a component. It is pretty straightforward: just move the HTML into the template of the component, move the computed into the component (adjusting it to work on the prop value ), and then – because it is operating on a prop – change the set function to use $emit rather than changing its value directly.

debouncedQuillEditor: {
  props: ['value', 'options'],
  template: '<quill-editor v-model="debouncedValue" :options="options"></quill-editor>',
  computed: {
    debouncedValue: {
      get() {
        return this.value;
      },
      set: _.debounce(function(newValue) {
        this.$emit('input', newValue);
      }, 100)
    }
  }
},

I made a fiddle to demonstrate. I made a second component to handle the output HTML, although it could have been included in the first component.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM