Lego tutorial
Az alábbiakban a Lego készletek című feladat megoldását fogom részletezni. A kék infoboxokban a feladat eredeti szövegei találhatóak, alattuk pedig a kifejtés, hogy hogyan kell megoldani. Ezt követően minden nagyobb egység alatt, a zöld lenyitható dobozokban látható a teljes fájl kódja.
Útvonalak
| Útvonal neve | Komponens | Url | Paraméterek |
|---|---|---|---|
home | index.vue | / | |
set | sets/[id].vue | /sets/:id | id: A készlet azonosítója |
create-set | sets/create.vue | /sets/create |
<template>
<BaseLayout>
<h1 class="text-6xl my-10">Hello! 👋</h1>
</BaseLayout>
</template>
<script>
import BaseLayout from "@layouts/BaseLayout.vue"
export default {
components: {
BaseLayout
}
}
</script>
<route lang="yaml">
name: home
</route>
Tárolók
ThemeStore
stores/ThemeStore.js fájlban található tárolót egy themes állapottal. Készítse el az alábbi függvényeket:state() {
return {
themes: []
}
},
getThemes(): Kérje le az összes témát a Backendben elkészült végpontról és tárolja el az előbbi állapotban.import { http } from "@utils/http"
actions: {
async getThemes() {
const response = await http.get(`themes`)
this.themes = response.data.data
},
},
getTheme(id): Azonosító alapján kérjen le egy témát és adja vissza.async getTheme(id) {
const response = await http.get(`themes/${id}`)
return response.data.data
},
A @stores/ThemeStore.mjs teljes tartalma...
SetStore
SetStore néven, amely tartalmaz egy sets állapotot. Készítse el az alábbi függvényeketHozzuk létre az src/stores mappában a SetStore.mjs fájlt, és készítsük el a tárolót az alábbi módon.
Figyeljünk oda rá, hogy a state() függvény esetén, mindig térjünk vissza magával az állapottal, különben nem fog helyesen működni a tároló!
import { defineStore } from "pinia"
export const useSetStore = defineStore('set-store',{
state(){
return{
sets:[]
}
},
})
getSets(): Kérje le az összes készletet a Backendben elkészült végpontról és tárolja el az előbbi állapotbanimport { http } from '@utils/http'
actions:{
async getSets(){
const response = await http.get(`sets`)
this.sets = response.data.data
},
}
getSet(id): Azonosító alapján kérjen le egy készletet és adja vissza.async getSet(id){
const response = await http.get(`sets/${id}`)
return response.data.data
},
createSet(data): Töltse fel a Backend megfelelő végpontjára a paraméterként kapott adatot.async createSet(data){
const response = await http.post(`sets`,data)
this.sets.push(response.data.data)
}
A @stores/SetStore.mjs teljes tartalma...
Komponensek
BaseTable
amber-100 és orange-100 színekkel, amely a következő oszlopokat tartalmazza rendre:Név, Korosztály, Elemszám, Értékelés, ÁrHozzuk létre először is magát a komponents a components mappában BaseTable.vue néven és adjuk meg az alap tag-eket hozzá.
<template>
</template>
<script>
</script>
Ezt követően a <template>-n belül elkezdhetjük a táblázat megadását.
<table class="w-full">
<thead>
<tr>
<th>Név</th>
<th>Korosztály</th>
<th>Elemszám</th>
<th>Értékelés</th>
<th>Ár</th>
</tr>
</thead>
<tbody>
<tr class="odd:bg-amber-100 even:bg-orange-100">
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
SetStore tároló alapján generálja a sorokat a táblázat.Importáljuk be a szükséges dolgokat első körben a <script>-en belül.
import { useSetStore } from '@stores/SetStore'
import { mapState } from 'pinia'
Ezt követően kössük össze a sets állapotot a komponensünkkel, amelyet egy számított állapoton keresztül hajtunk végre.
export default {
computed: {
...mapState(useSetStore, ['sets'])
}
}
Mostmár meg tudjuk oldani, hogy a táblázat sorai ez alapján generálódjanak. Egy v-for segítségével végig megyünk a sets tömbön és legeneráljuk belőle a sorokat, amiben ki is töltjük a megfelelő adatokat.
Figyeljünk arra, hogy a :key="set.id" fontos, ne hagyjuk le, különben később problémát okoz a sorok kezelésében!
<tr v-for="set of sets" :key="set.id" class="odd:bg-amber-100 even:bg-orange-100">
<td>{{ set.name }}</td>
<td>{{ set.age_range }}</td>
<td>{{ set.piece_count }}</td>
<td>{{ set.rating }}</td>
<td>{{ set.price }} Ft</td>
</tr>
yellow-500. Az név pedig legyen egy olyan hivatkozás, amely a készlet azonosítója alapján átvisz annak az oldalára!Alakítsuk át először az értékelést, ami így fog kinézni nekünk ezután:
<td>
<span class="p-1 bg-yellow-500">{{ set.rating }}</span>
</td>
És most nézzük a hivatkozást. Itt a <RouterLink> kmoponens segítségével fogjuk ezt megadni, ahol megadjuk az oldal nevét (set), ahova megyünk, illetve az átadni kívánt paramétereket (id).
<td>
<RouterLink :to="{ name: 'set', params: { id: set.id } }">{{ set.name }}</RouterLink>
</td>
Figyeljünk, hogy a cellák kifejezés az vonatkozik a fejlécre is!
<thead>
<tr>
<th class="p-2 text-center">Név</th>
<th class="p-2 text-center">Korosztály</th>
<th class="p-2 text-center">Elemszám</th>
<th class="p-2 text-center">Értékelés</th>
<th class="p-2 text-center">Ár</th>
</tr>
</thead>
<tbody>
<tr v-for="set of sets" :key="set.id" class="odd:bg-amber-100 even:bg-orange-100">
<td class="p-2 text-center">
<RouterLink :to="{ name: 'set', params: { id: set.id } }">{{ set.name }}</RouterLink>
</td>
<td class="p-2 text-center">{{ set.age_range }}</td>
<td class="p-2 text-center">{{ set.piece_count }}</td>
<td class="p-2 text-center"><span class="p-1 bg-yellow-500">{{ set.rating }}</span></td>
<td class="p-2 text-center">{{ set.price }} Ft</td>
</tr>
</tbody>
A @components/BaseTable.mjs teljes tartalma...
BaseCard
amber-600-as színnel.Induljunk ki szintén egy üres komponensből, amit ugyanúgy a components mappában hozunk lére BaseCard.vue néven
<template>
<div class="rounded-md border border-amber-600"></div>
</template>
<script>
</script>
amber-600, szöveg színe pedig fehér, valamint függőlegesen 2 egységnyi paddinget kapjon. Ezen kívül a teteje legyen szintén közepesen lekerekítve. <h3 class="bg-amber-600 text-white text-center rounded-t-md py-2"></h3>
<p class="p-4"></p>
::alert{type="info"}
A kártya vegyen át a szülőtől egy `title` és egy `content` tulajdonságot, amelyek szöveges típusúak. Ezeket helyezze el a kártyán a megfelelő helyre.
::
```html
<script>
export default {
props: {
title: String,
content: String,
}
}
</script>
<h3 class="bg-amber-600 text-white text-center rounded-t-md py-2">{{ title }}</h3>
<p class="p-4">{{ content }}</p>
A @components/BaseCard.vue teljes tartalma...
Gyökérkomponens
Importáljuk be a szükséges dolgokat első körben a <script>-en belül
import { mapActions } from 'pinia';
import { useSetStore } from '@stores/SetStore.mjs';
import { useThemeStore } from '@stores/ThemeStore.mjs';
Ezután kössük be a két lekérő függvényt a tárolókból a mapActions segítségével az export default {}-on belül
methods:{
...mapActions(useSetStore, ['getSets']),
...mapActions(useThemeStore, ['getThemes'])
},
Végül bővítski ki a mounted() függvénnyel, és hívjuk meg a két bekötött függvényt.
mounted(){
this.getSets()
this.getThemes()
}
A @/App.vue teljes tartalma...
Oldalak
Főoldal
BaseTable-t tartalmazza a BaseLayouton belül!
A Főcím szövege legyen: “LEGO készletek”<template>
<BaseLayout>
<h1 class="text-6xl my-10">LEGO készletek</h1>
<BaseTable />
</BaseLayout>
</template>
<script>
import BaseLayout from '@layouts/BaseLayout.vue'
import BaseTable from '@components/BaseTable.vue';
export default {
components: {
BaseLayout,
BaseTable
},
}
</script>
<route lang="yaml">
name: home
</route>
Részletek oldal
SetStore segítségével kér le! Ezen kívül egy töltést jelző állapotot, amelyet az adatok betöltődését követően állít!Készítsük el a belső állapotokat első körben.
<script>
export default {
data(){
set: null,
loading: true
}
}
</script>
Ezután importáljuk be a szükséges dolgokat
import { mapActions } from 'pinia'
import { useSetStore } from '@stores/SetStore.mjs'
Majd kössük be a megfelelő függvényünket a SetStore-ból
methods: {
...mapActions(useSetStore, ['getSet'])
},
Végül oldjuk meg a lekérdezést az oldal betöltésére.
async mounted() {
this.set = await this.getSet(this.$route.params.id)
this.loading = false
},
computed: {
price(){
if(this.set.price === 0){
return "Jelenleg nincs forgalomban"
}
return `${this.set.price} Ft`
}
},
BaseSpinner komponenst, amely középre van igazítva, felső margója 25 egység legyen.import BaseSpinner from '@components/layout/BaseSpinner.vue'
components:{
BaseCard,
BaseLayout,
BaseSpinner
}
<template>
<BaseLayout>
<BaseSpinner v-if="loading" class="block mx-auto mt-25" />
</BaseLayout>
</template>
<div v-else class="grid gap-4 grid-cols-4">
<div class="col-span-4"></div>
<div class="col-span-4 md:col-span-2 lg:col-span-1"></div>
<div class="col-span-4 md:col-span-2 lg:col-span-1"></div>
<div class="col-span-4 md:col-span-2 lg:col-span-1"></div>
<div class="col-span-4 md:col-span-2 lg:col-span-1"></div>
</div>
<div class="col-span-4">
<h1 class="text-6xl my-10">{{ set.theme.name }}: {{ set.name }}</h1>
</div>
BaseCard-ot tartalmazzon.- Korosztály
- Elemszám
- Értékelés
- Ár
<div v-else class="grid gap-4 grid-cols-4">
<div class="col-span-4">
<h1 class="text-6xl my-10">{{ set.theme.name }}: {{ set.name }}</h1>
</div>
<div class="col-span-4 md:col-span-2 lg:col-span-1">
<BaseCard title="Korosztály" :content="set.age_range" />
</div>
<div class="col-span-4 md:col-span-2 lg:col-span-1">
<BaseCard title="Elemszám" :content="set.piece_count" />
</div>
<div class="col-span-4 md:col-span-2 lg:col-span-1">
<BaseCard title="Értékelés" :content="set.rating" />
</div>
<div class="col-span-4 md:col-span-2 lg:col-span-1">
<BaseCard title="Ár" :content="price" />
</div>
</div>
A @pages/sets/[id].vue teljes tartalma...
Készlet létrehozása oldal
<FormKit type="form" :actions="false">
</FormKit>
Request-ek)!<FormKit type="form" :actions="false">
<FormKit type="text" label="Készlet neve" name="name"/>
<FormKit type="text" label="Korosztály" name="age_range"/>
<FormKit type="number" label="Elemszám" name="piece_count"/>
<FormKit type="number" label="Értékelés" name="rating"/>
<FormKit type="number" label="Ár" name="price"/>
<FormKit type="select" label="Téma" name="theme_id"/>
</FormKit>
A App\Http\Requests\StoreSetRequest tartalma...
ThemeStore-ban található themeOptions-ből töltse be.import { mapState } from 'pinia'
import { useThemeStore } from '@stores/ThemeStore.mjs'
computed:{
...mapState(useThemeStore, ['themeOptions'])
},
<FormKit type="select" label="Téma" name="theme_id" :options="themeOptions"/>
SetStore segítségével az adatok továbbítását, ezt követően átirányít a főoldalra oldalra.<FormKit type="submit" value="Új készlet rögzítése"/>
<FormKit type="form" :actions="false" @submit="submitForm">
import { mapState, mapActions } from 'pinia'
import { useSetStore } from '@stores/SetStore.mjs'
methods:{
...mapActions(useSetStore, ['createSet']),
}
async submitForm(data){
await this.createSet(data)
this.$router.push({name: 'home'})
}
A @pages/sets/create.vue teljes tartalma...