Skip to content

13. Voorbeeld [nuxt-10]: asyncData en loading

De functie [asyncData] in een pagina maakt het mogelijk om gegevens, vaak externe, asynchroon te laden. [nuxt] wacht tot de functie [asyncData] is voltooid voordat de levenscyclus van de pagina begint. De pagina wordt dus pas weergegeven zodra de externe gegevens zijn opgehaald. Deze functie wordt zowel door de server als door de client uitgevoerd volgens de volgende regels:

  • wanneer de pagina rechtstreeks bij de server wordt opgevraagd, voert alleen de server de functie [asyncData] uit;
  • vervolgens, tijdens het navigeren door de client, voert alleen de client de functie [asyncData] uit;

Uiteindelijk voert slechts één van beide, de client of de server, de functie uit. Wanneer de client de functie [asyncData] uitvoert, geeft [nuxt] bovendien een voortgangsbalk weer die kan worden geconfigureerd.

Met de functie [asyncData] kunnen pagina’s met hun gegevens aan zoekmachines worden geleverd, waardoor ze relevanter worden.

Het voorbeeld [nuxt-10] wordt in eerste instantie verkregen door het project [nuxt-01] te kopiëren:

Image

Alleen de pagina [page1] verandert.

13.1. De pagina [page1]

De code van de pagina [page1] is als volgt:


<!-- weergave nr. 1 -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigatie -->
    <Navigation slot="left" />
    <!-- bericht-->
    <b-alert slot="right" show variant="primary"> Page 1 -- result={{ result }} </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-console */
/* eslint-disable nuxt/no-timing-in-fetch-data */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'Page1',
  // gebruikte componenten
  components: {
    Layout,
    Navigation
  },
  // asynchrone gegevens
  asyncData(context) {
    // log
    console.log('[page1 asyncData started]')
    // we retourneren een promise
    return new Promise(function(resolve, reject) {
      // we simuleren een asynchrone functie
      setTimeout(function () {
        // het resultaat wordt asynchroon teruggegeven – hier een willekeurig getal
        resolve({ result: Math.floor(Math.random() * Math.floor(100)) })
        // log
        console.log('[page1 asyncData finished]')
      }, 5000)
    })
  },

  // levenscyclus
  beforeCreate() {
    console.log('[page1 beforeCreate]')
  },
  created() {
    console.log('[page1 created]')
  },
  beforeMount() {
    console.log('[page1 beforeMount]')
  },
  mounted() {
    console.log('[page1 mounted]')
  }
}
</script>
  • regels 26-39: de functie [asyncData]. We hebben deze functie al besproken (zie paragraaf link). Deze wordt uitgevoerd vóór de levenscyclus van de pagina. Om deze reden kan het sleutelwoord [this] niet in de functie worden gebruikt;
  • regel 30: de functie moet een [Promise]-promise retourneren of de async/await-syntaxis gebruiken;
  • regels 32-37: de asynchrone functie van de promise wordt gesimuleerd met een wachttijd van 5 seconden (regel 37);
  • regel 34: het resultaat van de asynchrone functie wordt weergegeven in de vorm van een object {result :...}. Het asynchrone object dat door de functie [asyncData] wordt geretourneerd, wordt geïntegreerd in het object [data] van de pagina. Daarom is het object [result] beschikbaar in regel 7 van de sjabloon, ook al had de pagina geen object [data] gedefinieerd;

13.2. Configuratie van de voortgangsbalk van [asyncData]

Wanneer de pagina [page1] het doel is van een navigatie binnen de client (modus SPA), voert de client de functie [asyncData] uit en geeft [nuxt] vervolgens een voortgangsbalk weer, die wordt verborgen zodra de functie [asyncData] het resultaat heeft weergegeven. Met de eigenschap [loading] van het bestand [nuxt.config.js] kan deze balk worden geconfigureerd:


loading: {
    color: 'blue',
    height: '5px',
    throttle: 200,
    continuous: true
},

Standaard is de laadafbeelding van [nuxt] een voortgangsbalk die de volledige breedte van de pagina beslaat. Deze balk heeft een kleur en een dikte. De gekleurde streep groeit geleidelijk van 0% tot 100% van zijn grootte, dus min of meer snel afhankelijk van de wachttijd.

  • regel 2: bepaalt de kleur van de voortgangsbalk;
  • regel 3: bepaalt de dikte van de balk in pixels;
  • regel 4: [throttle] is de vertraging in milliseconden voordat de animatie begint. Dit zorgt ervoor dat er geen animatiebeeld wordt weergegeven wanneer de functie [asyncData] snel resultaat oplevert;
  • regel 5: [continuous] bepaalt het gedrag van de animatie van de voortgangsbalk. Standaard groeit de balk geleidelijk van 0% tot 100% van zijn grootte, al dan niet sneller afhankelijk van de wachttijd. Met [continuous:true] groeit de gekleurde balk met een constante snelheid van 0 tot 100 % van zijn grootte, waarna het proces opnieuw begint zolang de functie [asyncData] geen resultaat heeft weergegeven;

13.3. Exécution

Laten we de applicatie starten en vervolgens handmatig de pagina [page1] bij de server opvragen:

Image

De logbestanden zien er als volgt uit:

Image

  • we zien dat alleen de server [1] de functie [asyncData] heeft uitgevoerd en dat hij dit vóór de paginacyclus heeft gedaan;

Laten we nu eens kijken naar de pagina die door de server is verzonden (broncode):


<!doctype html>
<html data-n-head-ssr>
<head>
  <title>Introduction à [nuxt.js]</title>
  <meta data-n-head="ssr" charset="utf-8">
  <meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
  <meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
  <link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
  <base href="/nuxt-10/">
  <link rel="preload" href="/nuxt-10/_nuxt/runtime.js" as="script">
  <link rel="preload" href="/nuxt-10/_nuxt/commons.app.js" as="script">
  <link rel="preload" href="/nuxt-10/_nuxt/vendors.app.js" as="script">
  <link rel="preload" href="/nuxt-10/_nuxt/app.js" as="script">
...
</head>
<body>
  <div data-server-rendered="true" id="__nuxt">
    <div id="__layout">
      <div class="container">
        <div class="card">
          <div class="card-body">
            <div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-success">
            <h4>[nuxt-10] : asyncData et loading</h4>
              </div>
            <div>
              <div class="row">
                <div class="col-2">
                  <ul class="nav flex-column">
                    <li class="nav-item">
                      <a href="/nuxt-10/" target="_self" class="nav-link">
                        Home
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-10/page1" target="_self" class="nav-link active nuxt-link-active">
                        Page 1
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-10/page2" target="_self" class="nav-link">
                        Page 2
                      </a>
                    </li>
                  </ul>
                </div> <div class="col-10"><div role="alert" aria-live="polite" aria-atomic="true" class="alert alert-primary"> Page 1 -- result=3 </div></div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script>window.__NUXT__ = (function (a, b, c) {
  return {
    layout: "default", data: [{ result: 3 }], error: null, serverRendered: true,
    logs: [
      { date: new Date(1574939615256), args: ["[page1 asyncData started]"], type: a, level: b, tag: c },
      { date: new Date(1574939620263), args: ["[page1 asyncData finished]"], type: a, level: b, tag: c },
      { date: new Date(1574939620285), args: ["[page1 beforeCreate]"], type: a, level: b, tag: c },
      { date: new Date(1574939620287), args: ["[page1 created]"], type: a, level: b, tag: c }
    ]
  }
    }("log", 2, ""));</script>
  <script src="/nuxt-10/_nuxt/runtime.js" defer></script>
  <script src="/nuxt-10/_nuxt/commons.app.js" defer></script>
  <script src="/nuxt-10/_nuxt/vendors.app.js" defer></script>
  <script src="/nuxt-10/_nuxt/app.js" defer></script>
</body>
</html>
  • regel 55: we zien dat de server een array [data] naar de client heeft verzonden, die het object [result:3] bevat, dat is geïntegreerd in het object [data] van de pagina [page1] van de server. Om ervoor te zorgen dat de client hetzelfde kan doen en dus dezelfde pagina kan weergeven als de server, stuurt de server het object [result] naar de client. We herinneren eraan dat de client de functie [asyncData] niet zal uitvoeren. Hij zal gewoon de door de server berekende gegevens gebruiken;

Laten we nu via het navigatiemenu van de pagina [Home] naar de pagina [Page 1] navigeren:

Image

  • op [1] verschijnt de voortgangsbalk;

Na 5 seconden verschijnt de pagina [Page 1]:

Image

De logbestanden zijn als volgt:

Image

We zien dat de client de functie [asyncData] heeft uitgevoerd vóór de levenscyclus van de pagina.