7

I'm trying to create a shuffle function in vue.js. So, for this i created a computed properties and then i call a method. but it doesn't working. I've created two more function 'add' and 'remove' these two working fine except 'shuffle'.

Throwing an error: Uncaught TypeError: this.moveIndex is not a function

var app = new Vue({
  el: '#root',
  data: {
    tasks: [1,8,9],
    nextNum: 10
  },
  computed: {
    moveIndex: function(array){
      var currentIndex = array.length, randomIndex, tempVal;
      for(var i = currentIndex - 1; i > 0; i--){
        randomIndex = Math.floor(Math.random() * currentIndex);
        tempVal = array[i];
        array[i] = array[randomIndex];
        array[randomIndex] = tempVal;
      }
      return array;
    }
  },
  methods: {
    randIndex: function(){
      return Math.floor(Math.random() * this.tasks.length);
    },
    add: function(){
      this.tasks.splice(this.randIndex(),0,this.nextNum++)
    },
    remove: function(){
      this.tasks.splice(this.randIndex(),1)
    },
    shuffle: function(){
      var arr = this.tasks;
      arr = this.moveIndex(arr)
    }
  }
});
.bar-enter-active, .bar-leave-active{
  transition: all 1s;
}
.bar-enter, .bar-leave-to{
  opacity: 0;
  transform: translateY(30px)
}
.bar-move{
  transition: transform 1s 
}
.numbers{
  margin-right: 10px;
  display: inline-block
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>

	<div id="root">
		<button @click="add">Add</button>
		<button @click="remove">Remove</button>
		<button @click="shuffle">Shuffle</button>
		<transition-group name="bar" tag="div">
			<span v-for="task in tasks" :key="task" class="numbers">{{task}}</span>
		</transition-group>
	</div>

3
  • 1
    You cannot call computed properties as a function. They are properties (vuejs.org/v2/guide/computed.html) . If you want a function move it to the methods and you can call it as such. Commented Jul 8, 2018 at 9:07
  • 1
    I cannot see a single reason why moveIndex would make sense as a computed. Put it into methods. Commented Jul 8, 2018 at 9:32
  • Also this a classic case of an x-y problem. Commented Jul 8, 2018 at 9:34

1 Answer 1

6

Computed properties are just getter functions that return a value and are dependent on other reactive properties.

1. Your computed property moveIndex is just modifying an array data property i.e this.tasks. So just use a method instead.

2. You are trying to directly modify an item of the this.tasks array using index. Vue cannot detect such array modifications.

So use this.$set() or Array.prototype.splice() instead.

Here are the changes:

var app = new Vue({
  el: "#root",
  data: {
    tasks: [1, 8, 9],
    nextNum: 10
  },
  methods: {
    randIndex: function() {
      return Math.floor(Math.random() * this.tasks.length);
    },
    add: function() {
      this.tasks.splice(this.randIndex(), 0, this.nextNum++);
    },
    remove: function() {
      this.tasks.splice(this.randIndex(), 1);
    },
    shuffle: function() {
      var array = this.tasks;
      var currentIndex = this.tasks.length;
      var randomIndex;
      var tempVal;

      for (var i = currentIndex - 1; i > 0; i--) {
        randomIndex = Math.floor(Math.random() * currentIndex);
        tempVal = array[i];
        this.$set(array, i, array[randomIndex]);
        this.$set(array, randomIndex, tempVal);
      }
    }
    
  }
});

Here is a working fiddle

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.