Erstellung dynamischer Routen in einer Nuxt-Anwendung

Avatar of Sarah Drasner
Sarah Drasner am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

In diesem Beitrag verwenden wir eine E-Commerce-Store-Demo, die ich erstellt und bei Netlify bereitgestellt habe, um zu zeigen, wie wir dynamische Routen für eingehende Daten erstellen können. Dies ist ein ziemlich gängiger Anwendungsfall: Sie erhalten Daten von einer API und wissen entweder nicht genau, welche Daten das sein könnten, es gibt viele davon oder sie könnten sich ändern. Glücklicherweise macht Nuxt den Prozess der Erstellung dynamischer Routen sehr nahtlos.

Legen wir los!

Die Seite erstellen

In diesem Fall haben wir einige Dummy-Daten für den Shop, die ich in mockaroo erstellt und im statischen Ordner gespeichert habe. Normalerweise würden Sie fetch oder axios und eine Aktion im Vuex-Store verwenden, um diese Daten zu sammeln. In jedem Fall speichern wir die Daten mit Vuex in store/index.js, zusammen mit dem UI-Status und einem leeren Array für den Warenkorb.

import data from '~/static/storedata.json'

export const state = () => ({
 cartUIStatus: 'idle',
 storedata: data,
 cart: []
})

Es ist wichtig zu erwähnen, dass wir in Nuxt nur eine .vue-Datei im Seitenverzeichnis erstellen müssen, um das Routing in der Anwendung einzurichten. Wir haben also eine index.vue-Seite für unsere Homepage, eine cart.vue-Seite für unseren Warenkorb usw. Nuxt generiert all das Routing für diese Seiten automatisch für uns.

Um dynamisches Routing zu erstellen, erstellen wir ein Verzeichnis, in dem diese Seiten untergebracht werden. In diesem Fall habe ich ein Verzeichnis namens /products erstellt, da dies die Routen sein werden: eine Ansicht jedes einzelnen Produktdetails.

In diesem Verzeichnis erstelle ich eine Seite mit einem Unterstrich und der eindeutigen Kennung, die ich pro Seite verwenden möchte, um die Routen zu erstellen. Wenn wir uns die Daten ansehen, die ich in meinem Warenkorb habe, sieht das so aus

[
 {
   "id": "9d436e98-1dc9-4f21-9587-76d4c0255e33",
   "color": "Goldenrod",
   "description": "Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.",
   "gender": "Male",
   "name": "Desi Ada",
   "review": "productize virtual markets",
   "starrating": 3,
   "price": 50.40,
   "img": "1.jpg"
 },
  …
]

Sie sehen, dass die ID für jeden Eintrag eindeutig ist, also ist das ein guter Kandidat für etwas, das wir verwenden können. Wir nennen die Seite

_id.vue

Jetzt können wir die ID der jeweiligen Seite in unseren Daten speichern, indem wir die Routenparameter verwenden

data() {
 return {
   id: this.$route.params.id,
  }
},

Für den obigen Eintrag wären unsere Daten, wenn wir sie in devtools ansehen würden

id: "9d436e98-1dc9-4f21-9587-76d4c0255e33"

Wir können dies nun verwenden, um alle anderen Informationen für diesen Eintrag aus dem Store abzurufen. Ich werde mapState verwenden

import { mapState } from "vuex";

computed: {
 ...mapState(["storedata"]),
 product() {
   return this.storedata.find(el => el.id === this.id);
 }
},

Und wir filtern die storedata, um den Eintrag mit unserer eindeutigen ID zu finden!

Nuxt-Konfiguration informieren

Wenn wir eine App mit yarn build erstellen würden, wären wir fertig. Aber wir verwenden Nuxt, um eine statische Seite zu erstellen, die wir in unserem Fall auf Netlify bereitstellen. Wenn wir Nuxt verwenden, um eine statische Seite zu erstellen, verwenden wir den Befehl yarn generate. Wir müssen Nuxt mit dem Befehl generate in nuxt.config.js auf die dynamischen Dateien aufmerksam machen.

Dieser Befehl erwartet eine Funktion, die ein Promise zurückgibt, das sich in einem Array auflöst, das so aussieht

export default {
  generate: {
    routes: [
      '/product/1',
      '/product/2',
      '/product/3'
    ]
  }
}

Um dies zu erstellen, bringen wir am Anfang der Datei die Daten aus dem statischen Verzeichnis herein und erstellen die Funktion

import data from './static/storedata.json'
let dynamicRoutes = () => {
 return new Promise(resolve => {
   resolve(data.map(el => `product/${el.id}`))
 })
}

Wir rufen die Funktion dann innerhalb unserer Konfiguration auf

generate: {
  routes: dynamicRoutes
},

Wenn Sie Ihre Daten stattdessen mit axios von einer API sammeln (was üblicher ist), würde es eher so aussehen

import axios from 'axios'
let dynamicRoutes = () => {
 return axios.get('https://your-api-here/products').then(res => {
   return res.data.map(product => `/product/${product.id}`)
 })
}

Und damit sind wir mit dem dynamischen Routing komplett fertig! Wenn Sie den Server herunterfahren und neu starten, sehen Sie die dynamischen Routen pro Produkt in Aktion!

Im letzten Teil dieses Beitrags machen wir weiter und zeigen, wie der Rest der Seite erstellt wurde und wie wir Artikel zu unserem Warenkorb hinzufügen, da dies vielleicht etwas ist, das Sie auch lernen möchten.

Die Seite befüllen

Jetzt können wir die Seite mit beliebigen Informationen und beliebiger Formatierung befüllen, da wir mit der berechneten Produkteigenschaft auf alle zugreifen können

<main>
 <section class="img">
   <img :src="`/products/${product.img}`" />
 </section>
 <section class="product-info">
   <h1>{{ product.name }}</h1>
   <h4 class="price">{{ product.price | dollar }}</h4>
   <p>{{ product.description }}</p>
 </section>
 ...
</main>

In unserem Fall möchten wir auch Artikel zum Warenkorb im Store hinzufügen. Wir fügen die Möglichkeit hinzu, Artikel hinzuzufügen und zu entfernen (wobei die Verringerung der Anzahl nicht unter Null fallen darf)

<p class="quantity">
 <button class="update-num" @click="quantity > 0 ? quantity-- : quantity = 0">-</button>
 <input type="number" v-model="quantity" />
 <button class="update-num" @click="quantity++">+</button>
</p>
...
<button class="button purchase" @click="cartAdd">Add to Cart</button>

In unseren methods dieser Komponente fügen wir den Artikel plus ein neues Feld, die Menge, zu einem Array hinzu, das wir als Payload an eine mutation im Store übergeben.

methods: {
 cartAdd() {
   let item = this.product;
   item.quantity = this.quantity;
   this.tempcart.push(item);
   this.$store.commit("addToCart", item);
 }
}

Im Vuex-Store prüfen wir, ob der Artikel bereits existiert. Wenn ja, erhöhen wir nur die Menge. Wenn nicht, fügen wir den gesamten Artikel mit Menge zum Warenkorb-Array hinzu.

addToCart: (state, payload) => {
 let itemfound = false
 state.cart.forEach(el => {
   if (el.id === payload.id) {
     el.quantity += payload.quantity
     itemfound = true
   }
 })
 if (!itemfound) state.cart.push(payload)
}

Wir können jetzt einen Getter im Store verwenden, um die Gesamtsumme zu berechnen, die wir schließlich an unsere Stripe-Serverless-Funktion übergeben werden (ein weiterer Beitrag dazu folgt bald!). Wir verwenden dafür einen Reduce, da Reduce sehr gut darin ist, einen Wert aus vielen abzurufen. (Ich habe hier weitere Details zur Funktionsweise von Reduce aufgeschrieben).

cartTotal: state => {
 if (!state.cart.length) return 0
 return state.cart.reduce((ac, next) => ac + next.quantity * next.price, 0)
}

Und da haben Sie es! Wir haben einzelne Produktseiten eingerichtet, und Nuxt generiert all unsere individuellen Routen zur Build-Zeit für uns. Sie würden Nuxt nicht widerstehen können, es selbst auszuprobieren. 😬