13. Beispiel [nuxt-10]: asyncData und Laden
Die Funktion [asyncData] in einer Seite ermöglicht das asynchrone Laden von Daten, die oft extern sind. [nuxt] wartet, bis die Funktion [asyncData] beendet ist, bevor der Lebenszyklus der Seite gestartet wird. Die Seite wird daher erst gerendert, wenn die externen Daten abgerufen wurden. Sie wird sowohl vom Server als auch vom Client gemäß den folgenden Regeln ausgeführt:
- Wenn die Seite direkt vom Server angefordert wird, führt nur der Server die Funktion [asyncData] aus;
- dann, während der clientseitigen Navigation, führt nur der Client die Funktion [asyncData] aus;
Letztendlich führt nur einer der beiden – Client oder Server – die Funktion aus. Wenn der Client die Funktion [asyncData] ausführt, zeigt [nuxt] zudem einen Fortschrittsbalken an, der konfiguriert werden kann.
Die Funktion [asyncData] ermöglicht es, Seiten zusammen mit ihren Daten an Suchmaschinen zu übermitteln, wodurch diese aussagekräftiger werden.
Das Beispiel [nuxt-10] wird zunächst durch Klonen des Projekts [nuxt-01] erstellt:

Nur die Seite [page1] ändert sich.
13.1. Die Seite [page1]
Der Code für die Seite [page1] lautet wie folgt:
<!-- vue n° 1 -->
<template>
<Layout :left="true" :right="true">
<!-- navigation -->
<Navigation slot="left" />
<!-- message-->
<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',
// components used
components: {
Layout,
Navigation
},
// asynchronous data
asyncData(context) {
// log
console.log('[page1 asyncData started]')
// we make a promise
return new Promise(function(resolve, reject) {
// we simulate an asynchronous function
setTimeout(function () {
// we make the result asynchronous - a random number here
resolve({ result: Math.floor(Math.random() * Math.floor(100)) })
// log
console.log('[page1 asyncData finished]')
}, 5000)
})
},
// life cycle
beforeCreate() {
console.log('[page1 beforeCreate]')
},
created() {
console.log('[page1 created]')
},
beforeMount() {
console.log('[page1 beforeMount]')
},
mounted() {
console.log('[page1 mounted]')
}
}
</script>
- Zeilen 26–39: die Funktion [asyncData]. Wir haben diese Funktion bereits behandelt (siehe verlinkten Abschnitt). Sie wird vor dem Seitenlebenszyklus ausgeführt. Aus diesem Grund kann das Schlüsselwort [this] innerhalb der Funktion nicht verwendet werden;
- Zeile 30: Sie muss ein [Promise] zurückgeben oder die async/await-Syntax verwenden;
- Zeilen 32–37: Die asynchrone Funktion des Promises wird mit einer Wartezeit von 5 Sekunden simuliert (Zeile 37);
- Zeile 34: Das Ergebnis der asynchronen Funktion wird als Objekt {result:...} zurückgegeben. Das von der Funktion [asyncData] zurückgegebene asynchrone Objekt wird in das [data]-Objekt der Seite integriert. Deshalb ist das Objekt [result] in Zeile 7 der Vorlage verfügbar, obwohl die Seite kein [data]-Objekt definiert hatte;
13.2. Konfigurieren des [asyncData]-Fortschrittsbalkens
Wenn die Seite [page1] das Ziel einer Navigation innerhalb des Clients ist (SPA-Modus), führt der Client die Funktion [asyncData] aus, und [nuxt] zeigt daraufhin einen Fortschrittsbalken an, den es ausblendet, sobald die Funktion [asyncData] ihr Ergebnis zurückgegeben hat. Mit der Eigenschaft [loading] in der Datei [nuxt.config.js] können Sie diesen Balken konfigurieren:
loading: {
color: 'blue',
height: '5px',
throttle: 200,
continuous: true
},
Standardmäßig ist das [nuxt]-Ladebild ein Fortschrittsbalken, der sich über die gesamte Breite der Seite erstreckt. Dieser Balken hat eine Farbe und eine Dicke. Die farbige Linie wächst allmählich von 0 % auf 100 % ihrer Größe an, wobei die Geschwindigkeit je nach Wartezeit variiert.
- Zeile 2: Legt die Farbe des Fortschrittsbalkens fest;
- Zeile 3: Legt die Dicke des Balkens in Pixeln fest;
- Zeile 4: [throttle] ist die Verzögerung in Millisekunden, bevor die Animation startet. Dies verhindert, dass ein Animationsbild erscheint, wenn die [asyncData]-Funktion ihr Ergebnis schnell zurückgibt;
- Zeile 5: [continuous] legt das Verhalten der Fortschrittsbalken-Animation fest. Standardmäßig wächst der Balken allmählich von 0 % auf 100 % seiner Größe, wobei die Geschwindigkeit je nach Wartezeit variiert. Mit [continuous:true] wächst der farbige Balken mit konstanter Geschwindigkeit von 0 auf 100 % seiner Größe und wiederholt sich dann, bis die Funktion [asyncData] ihr Ergebnis zurückgibt;
13.3. Ausführung
Starten wir die Anwendung und fordern wir dann manuell die Seite [page1] vom Server an:

Die Protokolle lauten wie folgt:

- Wir sehen, dass nur Server [1] die Funktion [asyncData] ausgeführt hat, und zwar vor dem Seitenwechsel;
Betrachten wir nun die vom Server gesendete Seite (Quellcode):
<!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>
- Zeile 55: Wir sehen, dass der Server dem Client ein Array [data] gesendet hat, das das Objekt [result:3] enthält, welches in das [data]-Objekt der Seite [page1] des Servers integriert wurde. Damit der Client dasselbe tun und somit dieselbe Seite wie der Server anzeigen kann, sendet der Server das [result]-Objekt an den Client. Beachten Sie, dass der Client die Funktion [asyncData] nicht ausführt. Er verwendet lediglich die vom Server berechneten Daten;
Navigieren wir nun über das Navigationsmenü von der Seite [Home] zur Seite [Page 1]:

- Bei [1] erscheint der Fortschrittsbalken;
Nach 5 Sekunden wird die Seite [Seite 1] angezeigt:

Die Protokolle lauten wie folgt:

Wir können sehen, dass der Client die Funktion [asyncData] vor dem Seitenlebenszyklus ausgeführt hat.