Vue Array Update and Filtration Sort

Posted by abriggs on Thu, 06 Jun 2019 01:25:29 +0200

Previous remarks

In order to increase the list rendering function, Vue adds a set of methods to observe arrays, and can display filtered or sorted copies of an array. This article will introduce Vue array update and filtering sort in detail.

 

Variation method

Vue contains a set of mutation methods for observing arrays that trigger view updates, including the following methods

push() receives any number of parameters, adds them one by one to the end of the array, and returns the length of the modified array.
pop() removes the last item from the end of the array, reduces the length value of the array, and then returns the removed item.
shift() removes the first item in the array and returns it, while reducing the length of the array by 1
unshift() adds any item to the front of the array and returns the new array length
splice() deletes some members of the original array and adds new members to the deleted location
sort() calls the toString() method for each array item, and then compares the resulting string sort to return the sorted array.
reverse() is used to reverse the order of arrays, returning the sorted array
<div id="example">
  <div>
    <button @click='push'>push</button>
    <button @click='pop'>pop</button>
    <button @click='shift'>shift</button>
    <button @click='unshift'>unshift</button>
    <button @click='splice'>splice</button>
    <button @click='sort'>sort</button>
    <button @click='reverse'>reverse</button>
  </div>
  <ul>
    <li v-for="item in items" >
      {{ item.message }}
    </li>
  </ul>  
</div>
<script>
var example = new Vue({
  el: '#example',
  data: {
    items: [
      {message: 'Foo' },
      {message: 'Bar' },
      {message: 'Baz' }
    ],
    addValue:{message:'match'}
  },
  methods:{
    push(){
      this.items.push(this.addValue)
    },
    pop(){
      this.items.pop()
    },
    shift(){
      this.items.shift()
    },
    unshift(){
      this.items.unshift(this.addValue)
    },
    splice(){
      this.items.splice(0,1)
    },
    sort(){
     this.items.sort()
    },
    reverse(){
      this.items.reverse()
    },
  }
})
</script>

 

Nonvariant method

The mutation method, as its name implies, changes the original array invoked by these methods. In contrast, there are also non-mutating methods, such as filter(), concat(), slice(). These do not change the original array, but always return a new array. When using non-mutation methods, old arrays can be replaced with new arrays

concat() first creates a copy of the current array, then adds the received parameters to the end of the copy, and finally returns the newly constructed array.
slice() creates a new array based on one or more items in the current array, accepts one or two parameters, that is, the start and end positions of the items to be returned, and finally returns the new array.
map() runs a given function on each item of the array, returning an array of the results of each function call
filter() runs a given function for each item in the array, which returns an array of true items.
<div id="example">
  <div>
    <button @click='concat'>concat</button>
    <button @click='slice'>slice</button>
    <button @click='map'>map</button>
    <button @click='filter'>filter</button>
  </div>
  <ul>
    <li v-for="item in items" >
      {{ item }}
    </li>
  </ul>  
</div>
<script>
var example = new Vue({
  el: '#example',
  data: {
    items: ['Foo','Bar','Baz'],
    addValue:'match'
  },
  methods:{
    concat(){
      this.items =  this.items.concat(this.addValue)
    },
    slice(){
      this.items =  this.items.slice(1)
    },
    map(){
      this.items =  this.items.map(function(item,index,arr){
        return index + item; 
      })
    },
    filter(){
      this.items =  this.items.filter(function(item,index,arr){
        return (index > 0); 
      })
    }
  }
})
</script>

The above actions do not cause Vue to discard the existing DOM and re-render the entire list. Vue implements some intelligent heuristic methods to maximize DOM element reuse, so it is very efficient to replace the original array with an array containing the same elements.

 

Undetectable

Due to JS constraints, Vue cannot detect the following changes in the array:

1. Setting an item directly with an index, for example: vm.items[indexOfItem] = newValue

2. When modifying the length of an array, for example: vm. items. length = new Length

<div id="example">
  <div>
    <button @click='setVal'>setVal</button>
    <button @click='setLength'>setLength</button>
    <button @click='pop'>pop</button>
  </div>
  <ul>
    <li v-for="item in items" >{{ item }}</li>
  </ul> 
  <p>{{ message }}</p> 
</div>
<script>
var watchFunc = function(){
  example.message = 'Data changes';
  setTimeout(function(){
    example.message = '';
  },500); 
}
var example = new Vue({
  el: '#example',
  data: {
    items: ['Foo','Bar','Baz'],
    message:'',
  },
  watch:{
    items:watchFunc
  },
  methods:{
    pop(){
      this.items.pop()
    },
    setVal(){
      this.items[0]= 'match';
    },
    setLength(){
      this.items.length = 2;
    }
  }
})
</script>

In the above code, direct setting of values and length can not detect changes using watch

The following two ways can achieve the same effect as vm.items[indexOfItem]=newValue, and also trigger status updates

// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)

To solve the second type of problem, splice can be used

example1.items.splice(newLength)
<div id="example">
  <div>
    <button @click='setVal1'>setVal1</button>
    <button @click='setVal2'>setVal2</button>
    <button @click='setLength'>setLength</button>
  </div>
  <ul>
    <li v-for="item in items" >{{ item }}</li>
  </ul> 
  <p>{{ message }}</p> 
</div>
<script>
var watchFunc = function(){
  example.message = 'Data changes';
  setTimeout(function(){
    example.message = '';
  },500); 
}
var example = new Vue({
  el: '#example',
  data: {
    items: ['Foo','Bar','Baz'],
    message:'',
  },
  watch:{
    items:watchFunc
  },
  methods:{
    setVal1(){
      Vue.set(this.items, 0, 'match')
    },
    setVal2(){
      this.items.splice(1, 1, 'xiaohuochai')
    },    
    setLength(){
      this.items.splice(2)
    }
  }
})
</script>

 

Filtering sort

Sometimes, a filtered or sorted copy of an array is displayed without actually changing or resetting the original data. In this case, you can create computational properties that return filtered or sorted arrays

[computed]

<div id="example">
  <ul>
    <li v-for="n in evenNumbers">{{ n }}</li>
  </ul> 
</div>
<script>
var example = new Vue({
  el: '#example',
  data: {
    numbers: [ 1, 2, 3, 4, 5 ],
  },
  computed: {
    evenNumbers: function () {
      return this.numbers.filter(function (number) {
        return number % 2 === 0
      })
    }
  }
})
</script>

[methods]

A method method method can be used in cases where computational attributes are not applicable (for example, in nested v-for loops)

<div id="example">
  <ul>
    <li v-for="n in even(numbers)">{{ n }}</li>
  </ul> 
</div>
<script>
var example = new Vue({
  el: '#example',
  data: {
    numbers: [ 1, 2, 3, 4, 5 ],
  },
  methods: {
    even: function (numbers) {
      return numbers.filter(function (number) {
        return number % 2 === 0
      })
    }
  }
})
</script>

Topics: Javascript Vue