Hoe kan ik de volgorde van een array omkeren met v-for en orderBy filter in Vue JS?

Ik gebruik Vue JS om viewmodel-bindingen te doen. In mijn data-object heb ik een reeks items die in oplopende volgorde zijn gesorteerd (van oud naar nieuw) en ik zou dit om op code gebaseerde redenen graag zo houden.

var v = new Vue({
    el: '#app',
    data: {
        items: [
            {id: 51,  message: 'first'},
            {id: 265, message: 'second'},
            {id: 32,  message: 'third'}
        ],
    }
}

Als ik de array in de sjabloon weergeef, wil ik de volgorde echter omdraaien, zodat deze aflopend is (van nieuw naar oud). Ik heb het volgende geprobeerd:

<ol>
    <li v-for="item in items | orderBy -1" track-by="id">

Dit werkte niet omdat het orderBy-filter een veldnaam als eerste argument lijkt te vereisen.

Is er een manier om dit in de sjabloon te bereiken met behulp van de v-for-syntaxis met behulp van het orderBy-filter? Of moet ik een aangepast reverse-filter maken?


Antwoord 1, autoriteit 100%

Eenvoudige en beknopte oplossing:

<li v-for="item in items.slice().reverse()">
//do something with item ...
</li>

Antwoord 2, autoriteit 24%

Opmerking:het onderstaande werkt in Vue 1, maar in Vue 2 zijn filters verouderd en kunt u
zal zien: ‘ Eigenschap of methode “reverse” is niet gedefinieerd op de
instantie maar waarnaar wordt verwezen tijdens het renderen.’ Zie tdom_93’santwoord voor
vue2.

U kunt een aangepast filter maken om de artikelen in omgekeerde volgorde te retourneren:

Vue.filter('reverse', function(value) {
  // slice to make a copy of array, then reverse the copy
  return value.slice().reverse();
});

Gebruik het vervolgens in de uitdrukking v-for:

<ol>
    <li v-for="item in items | reverse" track-by="id">

https://jsfiddle.net/pespantelis/sgsdm6qc/


Antwoord 3, autoriteit 23%

In plaats van de volgorde van de elementen voor het maken om te keren, verander ik alleen de volgorde van de weergave.

<ol class="reverseorder">
    <li v-for="item in items" track-by="id">

En mijn CSS

<style>
.reverseorder {
  display: flex;
  flex-direction: column-reverse;
}
</style>

Het is niet nodig om de array te klonen en om te keren.


Antwoord 4, autoriteit 22%

Update voor Vue2

Ik wil enkele manieren laten zien waarop u met gegevens kunt werken en geen filters kunt gebruiken, aangezien deze verouderdzijn in Vue2:

binnen berekende eigendom

Gebruik berekende eigenschappen in plaats van filters, wat veel beter is omdat u die gegevens overal in een component kunt gebruiken, niet alleen in een sjabloon:
jsFiddle

computed: {
    reverseItems() {
        return this.items.slice().reverse();
  }     
}

in Vuex getter eigendom

Als je Vuex gebruikt en je gegevens opslaat in het store.stateobject. De beste manier om een ​​transformatie uit te voeren met gegevens die in de staat zijn opgeslagen, is door dat te doen in het getters-object (bijvoorbeeld door een lijst met items te filteren en ze te tellen, omgekeerde volgorde enzovoort…)

getters: {
    reverseItems: state => {
        return state.items.slice().reverse();
    }
}

en de status ophalen van getters in de berekende eigenschap van de component:

computed: {
    showDialogCancelMatch() {
        return this.$store.state.reverseItems;
    }
}

Antwoord 5

Gebaseerd op het feit dat de richtlijn v-forniet alleen een array kan accepteren, maar ook elk ander geldig JavaScript itereerbaar object(tenminste in Vue 2.6+ en Vue 3 releases), kunnen we ons eigen itereerbare object maken om door een benodigde array in de tegenovergestelde richting te lopen. Ik heb een zeer vereenvoudigd uitvoerbaar voorbeeld gemaakt (voor meer details – bekijk informatie over de JavaScript-iteratorprotocol).

class Iterable {
  constructor(arr) {
    this.arr = arr;
  }
  *[Symbol.iterator]() {
    const arr = this.arr;
    for (let i = arr.length - 1; i >= 0; i--) yield arr[i];
  }
  getIterable(isReversedOrder) {
    return isReversedOrder ? this : this.arr;
  }
}
Vue.component('list', {
  props: ['iterable'],
  template: '<ul><li v-for="(el, i) in iterable" :key="`${i}-${el}`">{{ el }}</li></ul>'
});
const app = new Vue({
  data() {
    return {
      todos: new Iterable(['Learn JavaScript', 'Learn Vue', 'Learn Vuex']),
      isReversed: true,
      inputValue: ''
    };
  },
  computed: {
    computedTodos() {
      return this.todos.getIterable(this.isReversed);
    }
  },
  methods: {
    toggleReverse() {
      this.isReversed = !this.isReversed;
    },
    addTodo() {
      this.inputValue && this.todos.arr.push(this.inputValue);
      this.inputValue = '';
    }
  }
});
app.$mount('#app');
<!DOCTYPE html>
<html>
<body style="display: flex; justify-content: center;">
    <div id="app">
        <button @click="toggleReverse">Toggle reverse to {{ !isReversed }}</button>
        <br />
        <input v-model="inputValue" style="margin-top:5px;" />
        <button @click="addTodo" :disabled="!inputValue">Add todo</button>
        <!-- <ul><li v-for="(todo, i) in computedTodos" :key="`${i}-${todo}`">{{ todo }}</li></ul> -->
        <list :iterable="computedTodos" />
    </div>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    <script src="script.js"></script>
</body>
</html>

Snippet uitvouwen


Antwoord 6

De v-for-richtlijn ondersteunt niet achteruit itereren, dus als u op nieuwste wilt bestellen, moet u een ander veld toevoegen om aan te geven wanneer het item is toegevoegd, of idom elke keer dat een item wordt toegevoegd te verhogen.

Vervolgens, met fieldals veld dat de toegevoegde bestelling aangeeft:

<li v-for="item in items | orderBy 'field' -1" track-by="id">

Antwoord 7

Voor mijn gebruik (dat weliswaar blijkbaar anders is dan de OP…) wilde ik de indices van de array in omgekeerde volgordein de v-for “loop” hebben.

Mijn oplossing was om een ​​Vue-app-methode reverseRange(length)te maken die een array van gehele getallen retourneert van lengte-1 tot 0. Ik heb die vervolgens gebruikt in mijn v-for-richtlijn en verwees eenvoudig naar mijn Array-elementen als myArray[index]elke keer dat ik het nodig had.

Op die manier stonden de indexen in omgekeerde volgorde en kon ik ze vervolgens gebruiken om toegang te krijgen tot elementen van de array.

Ik hoop dat dit iemand helpt die op deze pagina is beland met deze subtiele nuance in hun vereisten, zoals ik.


Antwoord 8

Je kunt lodash reversegebruiken:

<li v-for="item in _.reverse(items)">

Antwoord 9

Misschien mis ik hier enkele nadelen, maar hoe zit het met het herhalen van de array vanaf het einde om te beginnen met het gebruik van een index?

<ol>
  <li v-for="i in items.length" :set="item = items[items.length - i]">

Als je array uit duizenden elementen bestaat, is het waarschijnlijk niet de meest efficiënte aanpak om het elke keer met .slice().reverse()te kopiëren.

Upd.: note, :setis geen officiële maniervoor het definiëren van variabelen in sjabloon, het werkt gewoon. Als alternatief zou de variabele itemkunnen worden vervangen door een aanroep van een of andere getItem(i)-methode die de items[items.length - i]uitdrukking.

Other episodes