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. 😬
Das war eine unglaubliche Hilfe, danke Sarah! Ich habe eine lokale Seite mit WordPress eingerichtet, die einen Produkt-Post-Typ über die REST-API bereitstellt. Dieser Leitfaden hat es ziemlich einfach gemacht
Danke für diesen Artikel, er ist wirklich klar :)
Ich habe zwei Fragen
1- Denken Sie, es ist möglich, SEO-freundliche URLs zu haben? Z.B.
/products/[ID]-[SLUG]statt nur/products/[ID]2- Wissen Sie, wie Nuxt & Netlify die statische Seitengenerierung handhaben, wenn Sie mehrere tausend Produkte haben? Da für jedes Produkt eine statische Seite generiert wird, könnte der Build- und Deployment-Prozess beeinträchtigt werden?
Besser einen beschreibenden Namen haben
Toller Artikel, hoffe, auf meinem nächsten Projekt implementieren zu können.. :)
Hat wie ein Zauber funktioniert! Nochmals danke, Sarah.