Search code examples
vue.jsvue-componentvue-property-decorator

What is affecting on will Vue computed property re-computed or no?


I expect that currentSelectionViewContent will be re-computed each time when selectedOptionsIndexes has changed. Really, sometimes it works, sometimes - not.

import { Component, Prop, Vue, Watch } from "vue-property-decorator";

@Component({
  template
})
export class SelectField extends Vue {

  private onNewOptionSelected(newOption: SelectField.Option, indexInArray: number): void {

    console.log("~~~~~~~~~~~~~~~");
    console.log(JSON.stringify(this.selectedOptionsIndexes, null, 2));

    this.selectedOptionsIndexes[0] = indexInArray;

    console.log(JSON.stringify(this.selectedOptionsIndexes, null, 2));
    console.log("--------------");

    if (isUndefined(newOption.key)) {
      this.$emit("change", newOption.relatedEntity);
    } else {
      this.$emit("change", newOption.key);
    }
  }

  // Vue computed property in "vue-property-decorator" syntax
  private get currentSelectionViewContent(): string {
    console.log("Recomputing ...");
    switch (this.selectedOptionsIndexes.length) {
      case 0:
        return SelectField.DEFAULT_NOTHING_SELECTED_PLACEHOLDER;
      case 1:
        return this.selectOptions[this.selectedOptionsIndexes[0]].title;
      default:
        return SelectField.DEFAULT_MULTIPLE_OPTIONS_SELECTED_LETTERING;
    }
  }
}

Working case:

enter image description here

Not working case (no re-computing):

enter image description here

I sorry about was not created the repro for this case (the reproducing of component where this problem causes, it's dependencies and also environment) takes too long time. If you can not understand what wrong here without repro, please just teach me what is affecting on will Vue computed property re-computed or no.


Solution

  • Vue has certain behavior around arrays to be aware of. From the docs:

    Vue cannot detect the following changes to an array:

    • When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
    • When you modify the length of the array, e.g. vm.items.length = newLength

    To ensure Vue sees your array change, always make a copy of the array and re-assign it, like this:

    var updatedIndexes = [...this.selectedOptionsIndexes]; // Copies array
    updatedIndexes[0] = indexInArray; // Update the copy
    this.selectedOptionsIndexes = updatedIndexes; // Overwrite with copy