de Hassan Djirdeh

O introducere la redarea dinamică a listelor în Vue.js

O introducere la redarea dinamica a listelor in Vuejs

Redarea listelor este una dintre cele mai utilizate practici în dezvoltarea web front-end. Redarea dinamică a listelor este adesea utilizată pentru a prezenta utilizatorului o serie de informații grupate în mod similar într-un format concis și prietenos. În aproape fiecare aplicație web pe care o folosim, putem vedea liste de conținut în numeroase zone ale aplicației.

În acest articol vom aduna o înțelegere a lui Vue v-for directivă în generarea listelor dinamice. Vom parcurge, de asemenea, câteva exemple de ce key atributul trebuie utilizat atunci când faceți acest lucru.

Deoarece vom explica lucrurile cu atenție când începem să scriem cod, acest articol presupune că nu veți avea cunoștințe sau foarte puține cunoștințe cu Vue (și / sau alte cadre JavaScript).

Studiu de caz: Twitter

Vom folosi Stare de nervozitate ca studiu de caz pentru acest articol.

Când sunteți conectat și pe ruta principală de indexare a Twitter, ni se prezintă o vizualizare similară cu aceasta:

1611261608 583 O introducere la redarea dinamica a listelor in Vuejs

Pe pagina de pornire, ne-am obișnuit să vedem o listă de tendințe, o listă de tweets, o listă de potențiali adepți etc. Conținutul afișat în aceste liste depinde de o multitudine de factori – istoricul nostru Twitter, pe care îl urmărim, aprecierile noastre și așa mai departe. Ca urmare, putem spune că toate aceste date sunt dinamic.

Deși aceste date sunt obținute dinamic, cale aceste date sunt afișate rămân aceleași. Acest lucru se datorează în parte utilizării componente web reutilizabile.

De exemplu, putem vedea lista de tweets ca o listă de single tweet-component obiecte. Ne putem gândi tweet-component ca un shell care preia date de fel, cum ar fi numele de utilizator, mânerul, tweet-ul și avatarul, printre alte piese, și afișează pur și simplu acele piese într-un markup consistent.

1611261608 980 O introducere la redarea dinamica a listelor in Vuejs

Să presupunem că am vrut să redăm o listă de componente (cum ar fi o listă de tweet-component elemente) bazate pe o sursă mare de date obținută de la un server. În Vue, primul lucru care ar trebui să vină în minte pentru a realiza acest lucru este v-for directivă.

Directiva v-for

v-for directiva este utilizată pentru a reda o listă de articole pe baza unei surse de date. Directiva poate fi utilizată pe un element șablon și necesită o sintaxă specifică de-a lungul liniilor:

1611261608 482 O introducere la redarea dinamica a listelor in Vuejs

Să vedem un exemplu în practică. În primul rând, vom presupune că am obținut deja o colecție de date tweet:

const tweets = [
  {
    id: 1,
    name: 'James',
    handle: '@jokerjames',
    img: 'https://semantic-ui.com/images/avatar2/large/matthew.png',
    tweet: "If you don't succeed, dust yourself off and try again.",
    likes: 10,
  },
  { 
    id: 2,
    name: 'Fatima',
    handle: '@fantasticfatima',
    img: 'https://semantic-ui.com/images/avatar2/large/molly.png',
    tweet: 'Better late than never but never late is better.',
    likes: 12,
  },
  {
    id: 3,
    name: 'Xin',
    handle: '@xeroxin',
    img: 'https://semantic-ui.com/images/avatar2/large/elyse.png',
    tweet: 'Beauty in the struggle, ugliness in the success.',
    likes: 18,
  }
]

tweets este o colecție de tweet obiecte cu fiecare tweet conținând detalii despre tweetul respectiv – un identificator unic, numele / identificatorul contului, mesajul tweet și așa mai departe. Să încercăm acum să folosim v-for directivă pentru a reda o listă de componente tweet pe baza acestor date.

În primul rând, vom crea instanța Vue – inima aplicației Vue. Vom monta / atașa instanța noastră la un element DOM de id appși atribuiți tweets colectare ca parte a obiectului de date al instanței.

new Vue({
  el: '#app',
  data: {
    tweets
  }
});

Acum vom continua și vom crea un tweet-component că a noastră v-fordirectiva va fi utilizată pentru a reda o listă. Vom folosi globalul Vue.componentconstructor pentru a crea o componentă numită tweet-component:

Vue.component('tweet-component', {
  template: `  
    <div class="tweet">
      <div class="box">
        <article class="media">
          <div class="media-left">
            <figure class="image is-64x64">
              <img :src="https://www.freecodecamp.org/news/an-introduction-to-dynamic-list-rendering-in-vue-js-a70eea3e321/tweet.img" alt="Image">
            </figure>
          </div>
          <div class="media-content">
            <div class="content">
              <p>
                <strong>{{tweet.name}}</strong> <small>{{tweet.handle}}</small>
                <br>
                {{tweet.tweet}}
              </p>
            </div>
              <div class="level-left">
                <a class="level-item">
                  <span class="icon is-small"><i class="fas fa-heart"></i></span>
                  <span class="likes">{{tweet.likes}}</span>
                </a>
              </div>
          </div>
        </article>
      </div>
    </div>  
  `,
  props: {
    tweet: Object
  }
});

Câteva lucruri interesante de remarcat aici:

  1. tweet-component se așteaptă la tweet obiect prop așa cum se vede în cerința de validare a propprops: {tweet: Object}). Dacă componenta este redată cu un tweet prop adică nu un obiect, Vue va emite avertismente.
  2. Legăm proprietățile obiectului tweet prop de șablonul componentei cu ajutorul sintaxei Mustache: {{ }}.
  3. Marcajul componentei se adaptează Elementul Bulma’s Box deoarece reprezintă o bună asemănare cu un tweet.

În șablonul HTML, va trebui să creăm marcajul în care va fi montată aplicația noastră Vue (adică elementul cu ID-ul app). În cadrul acestui marcaj, vom folosi fișierul v-for directivă pentru redarea unei liste de tweets.

De cand tweets este colectarea datelor pe care o vom itera, tweet va fi un alias adecvat de utilizat în directivă. În fiecare redat tweet-component, bine de asemenea treceți în iterație tweet obiect ca elemente de recuzită pentru a fi accesat în componentă.

<div id="app" class="columns">
  <div class="column">
    <tweet-component v-for="tweet in tweets" :tweet="tweet"/>
  </div>
</div>

Indiferent de Cum mai multe obiecte tweet vor fi introduse în colecție sau cum se vor schimba în timp – configurarea noastră va reda întotdeauna toate tweet-urile din colecție în același marcaj pe care îl așteptăm.

Cu ajutorul unor CSS personalizate, aplicația noastră va arăta cam așa:

Deși totul funcționează conform așteptărilor, este posibil să ni se solicite un sfat Vue în consola browserului nostru:

[Vue tip]: <tweet-component v-for="tweet in tweets">: component lists rendered with v-for should have explicit keys...

Notă: Este posibil să nu puteți vedea avertismentul în consola browserului atunci când rulați codul prin CodePen.

De ce Vue ne spune să specificăm chei explicite în lista noastră atunci când totul funcționează conform așteptărilor?

Atributul cheie

Este o practică obișnuită să specificați un atribut cheie pentru fiecare element iterat dintr-un randat v-for listă. Acest lucru se datorează faptului că Vue folosește key atribut a crea legături unice pentru identitatea fiecărui nod.

Să explicăm mai multe – dacă au existat modificări dinamice ale interfeței de utilizare a listei noastre (de exemplu, ordinea articolelor listei este amestecată), Vue va opta pentru schimbarea datelor din fiecare element in schimb de a muta elementele DOM în consecință. Aceasta nu va fi o problemă în majoritatea cazurilor. Cu toate acestea, în anumite cazuri în care v-for lista depinde de starea DOM și / sau starea componentelor copil, acest lucru poate provoca un comportament neintenționat.

Să vedem un exemplu în acest sens. Ce se întâmplă dacă componenta noastră simplă tweet conține acum un câmp de introducere care va permite utilizatorului să răspundă direct la mesajul tweet? Vom ignora modul în care acest răspuns ar putea fi trimis și ne vom adresa pur și simplu noul câmp de intrare:

1611261608 389 O introducere la redarea dinamica a listelor in Vuejs

Vom include acest nou câmp de introducere pe șablonul de tweet-component:

Vue.component('tweet-component', {
  template: `
    <div class="tweet">
      <div class="box">
        // ...
      </div>
      <div class="control has-icons-left has-icons-right">
        <input class="input is-small" placeholder="Tweet your reply..." />
        <span class="icon is-small is-left">
          <i class="fas fa-envelope"></i>
        </span>
      </div>
    </div>
  `,
  props: {
    tweet: Object
  }
});

Să presupunem că am vrut să introducem o altă caracteristică nouă în aplicația noastră. Această caracteristică ar presupune permisiunea utilizatorului de a amesteca aleatoriu o listă de tweets.

Pentru a face acest lucru, mai întâi putem include un „Shuffle!” butonul din șablonul nostru HTML:

<div id="app" class="columns">
  <div class="column">
    <button class="is-primary button" @click="shuffle">
      Shuffle!
    </button>
    <tweet-component v-for="tweet in tweets" :tweet="tweet"/>
  </div>
</div>

Am atașat un ascultător de evenimente de clic pe elementul buton pentru a apela un shuffle metoda la declanșare. În cazul nostru Vue, vom crea fișierul shuffle metodă responsabilă pentru amestecarea aleatorie a tweets colecție în instanță. Vom folosi lodash’s _amesteca metodă pentru a realiza acest lucru:

new Vue({
  el: '#app',
  data: {
    tweets
  },
  methods: {
    shuffle() {
      this.tweets = _.shuffle(this.tweets)
    }
  }
});

Să încercăm! Dacă facem clic pe Shuffle de câteva ori, vom observa că elementele noastre de tweet sunt asortate aleatoriu cu fiecare clic.

Cu toate acestea, dacă tastăm unele informații în intrarea fiecărei componente și atunci faceți clic pe Shuffle, vom observa că se întâmplă ceva ciudat:

O introducere la redarea dinamica a listelor in Vuejs

Deoarece nu am optat pentru utilizarea key atribut, Vue nu a creat legături unice pentru fiecare nod tweet. Ca rezultat, atunci când ne propunem să reordonăm tweet-urile, Vue ia în considerare abordarea de economisire mai performantă Schimbare (sau patch-uri) date din fiecare element. Întrucât starea temporară DOM (adică textul introdus) rămâne în loc, experimentăm această nepotrivire neintenționată.

Iată o diagramă care ne arată datele care sunt patch-uri pe fiecare element și starea DOM care rămâne în loc:

1611261608 560 O introducere la redarea dinamica a listelor in Vuejs

Pentru a evita acest lucru; va trebui să atribuim un unic cheie tuturor tweet-componentredate în listă.

Vom folosi id de o tweet să fie identificatorul unic, deoarece ar trebui să spunem în siguranță un tweet id nu ar trebui să fie egală cu cea a altuia. Deoarece folosim valori dinamice, vom folosi v-bind directivă pentru a ne lega cheia de tweet.id:

<div id="app" class="columns">
  <div class="column">
    <button class="is-primary button" @click="shuffle">
      Shuffle!
    </button>
    <tweet-component
      v-for="tweet in tweets"
      :tweet="tweet"
      :key="tweet.id"
    />
  </div>
</div>

Acum, Vue recunoaște identitatea nodului fiecărui tweet, așa că va fi reordonează componentele atunci când intenționăm să amestecăm lista.

1611261608 883 O introducere la redarea dinamica a listelor in Vuejs

Tranziții

Deoarece fiecare componentă de tweet este acum mutată în consecință, putem face acest lucru cu un pas mai departe și putem folosi Vue’s transition-group la spectacol modul în care elementele sunt reordonate.

Pentru a face acest lucru, vom adăuga fișierul transition-group ca element de împachetare a v-for listă. Vom specifica un nume de tranziție pentru tweets și să declare că grupul de tranziție ar trebui redat ca un div element.

<div id="app" class="columns">
  <div class="column">
    <button class="is-primary button" @click="shuffle">
      Shuffle!
    </button>
    <transition-group name="tweets" tag="div">
      <tweet-component
         v-for="tweet in tweets"
         :tweet="tweet"
         :key="tweet.id"
      />
    </transition-group>
  </div>
</div>

Pe baza numelui tranziției, Vue va recunoaște automat dacă au fost specificate tranziții / animații CSS. Deoarece ne propunem să invocăm o tranziție pentru circulaţie de elemente din listă, Vue va căuta o tranziție CSS specificată de-a lungul liniei tweets-move (Unde tweets este numele dat grupului nostru de tranziție).

Ca urmare, vom introduce manual un .tweets-move clasă care are un tip și un timp de tranziție specificat:

#app .tweets-move {
  transition: transform 1s;
}

Notă: Aceasta este o privire foarte scurtă asupra aplicării tranzițiilor de listă. Asigurați-vă că verificați Vue docs pentru informații detaliate despre toate tipurile de tranziții care pot fi aplicate!

Al nostru tweet-component elementele vor acum tranziție în mod corespunzător între locații atunci când este invocat un amestec. Incearca! Tastați câteva informații în câmpurile de introducere și faceți clic pe „Shuffle!” de câteva ori.

Destul de cool, nu? Fara key atribut, elementul grup de tranziție nu poate fi utilizat pentru a crea tranziții de listă întrucât elementele sunt patch-uri la locul lor în loc să fie reordonate.

În cazul în care key atributul să fie întotdeauna folosit? Este recomandat. Vue docs specificați că atributul cheie trebuie omis numai dacă:

  • Dorim în mod intenționat modul implicit de corecție a elementelor din motive de performanță.
  • Conținutul DOM este suficient de simplu.

Concluzie

Și iată-l! Sperăm că acest scurt articol descrie cât de util este v-for Directiva este, de asemenea, oferită un pic mai mult context pentru motivul pentru care key atributul este adesea folosit. Spuneți-mi dacă aveți întrebări / gânduri!

Dacă ți-a plăcut stilul meu de a scrie și ești potențial interesat să înveți cum să construiești aplicații din lumea reală cu Vue, s-ar putea să-ți placă cartea Fullstack Vue: Ghidul complet pentru Vue.js că am ajutat la publicare! Cartea acoperă numeroase fațete ale Vue, inclusiv rutarea, gestionarea simplă a stării, gestionarea formularelor, Vuex, persistența serverului și testarea, printre alte subiecte. Dacă sunteți interesat și / sau doriți să încercați un exemplu de capitol, puteți obține mai multe informații de pe site-ul nostru https://fullstack.io/vue!

Dacă aveți întrebări / gânduri / opinii, sunteți binevenit să vă contactați oricând @djirdehh!