Vue komponent a composable vzory dizajnu: Návod na štart
Táto príručka poskytuje praktický prehľad Vue komponent a composable vzorov dizajnu, s tipmi a príkladmi, prispôsobenými vývojárom vo vašom startupe. Využíva poznatky z rôznych zdrojov, aby vám pomohla napísať čistší, ľahšie udržiavateľný a škálovateľný Vue aplikácie.
Vzory dizajnu komponentov
1. Vzor komponentov
Extrahovanie opätovne použiteľných komponentov z existujúcich komponentov zjednodušuje kód a zvyšuje opätovnú použiteľnosť. To podporuje princíp jednej zodpovednosti, vďaka čomu je vaša kódová základňa modulárnejšia a udržiavateľnejšia.
Tip: Identifikujte a extrahovajte skryté komponenty v rámci vášho existujúceho kódu. Hľadajte opakované prvky UI alebo logiku, ktorú je možné zapúzdriť.
Príklad:
<!-- Pred: Komplexný formulár -->
<template>
<div>
<label for="name">Meno:</label>
<input type="text" id="name" v-model="name">
<label for="email">Email:</label>
<input type="email" id="email" v-model="email">
<button @click="submitForm">Poslať</button>
</div>
</template>
<!-- Po: Využívanie komponentov -->
<template>
<div>
<InputField label="Meno" v-model="name" type="text" />
<InputField label="Email" v-model="email" type="email" />
<SubmitButton @click="submitForm" />
</div>
</template>
2. Čisté komponenty
Cieľom sú komponenty, ktoré nielen pracujú, ale aj pracujú dobre, berúc do úvahy čitateľnosť kódu, udržiavateľnosť a testovateľnosť. Čisté komponenty sú ľahké na pochopenie, úpravu a ladenie.
Tip: Napíšte komponenty, ktoré sú ľahké na pochopenie a udržiavanie. Používajte jasné konvencie pomenovania, konzistentné formátovanie a jasne definované zodpovednosti.
Príklad:
<!-- Zlé: Komponent so zmiešanými opatreniami -->
<template>
<div>
<button @click="handleClick">{{ buttonText }}</button>
<div v-if="showDetails">{{ details }}</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const buttonText = ref('Zobraziť podrobnosti');
const showDetails = ref(false);
const details = ref('');
async function handleClick() {
showDetails.value = !showDetails.value;
if (showDetails.value) {
details.value = await fetchData();
}
}
</script>
<!-- Dobrá: Komponent so zameranou zodpovednosťou -->
<template>
<div>
<ShowDetailsButton @click="toggleDetails" :text="buttonText" />
<DetailsDisplay v-if="showDetails" :details="details" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import ShowDetailsButton from './ShowDetailsButton.vue';
import DetailsDisplay from './DetailsDisplay.vue';
const showDetails = ref(false);
const details = ref('');
const buttonText = ref('Zobraziť podrobnosti');
async function toggleDetails() {
showDetails.value = !showDetails.value;
if (showDetails.value) {
details.value = await fetchData();
}
}
</script>
3. Viacnásobné komponenty v jednom súbore
Na malé, samostatne uzavreté komponenty zvážte, aby ste ich zips v rovnakom súbore. To môže znížiť počet súborov vo vašom projekte a zlepšiť rýchlosť vývoja, obzvlášť pre komponenty, ktoré sú pevne viazané.
Tip: Vyhnite sa vytváram zbytočných súborov na jednoduché komponenty. Použite tento prístup na komponenty, ktoré sa používajú len na jednom mieste.
Príklad:
<template>
<div>
<MyButton @click="handleClick">Klikni ma</MyButton>
</div>
</template>
<script setup>
import MyButton from './MyButton.vue';
function handleClick() {
alert('Tlačidlo bolo kliknuté!');
}
</script>
<template>
<button @click="$emit('click')">
<slot></slot>
</button>
</template>
<script setup>
defineEmits(['click']);
</script>
4. Vzor kontrolovaných rekvizít
Tento vzor vám umožňuje prepísať interný stav komponenty z rodičovského prvku. To je užitočné, keď potrebujete vynútiť stav komponenty zvonka, ako je kontrola viditeľnosti modálny alebo výberu v rozbaľovacom menu.
Tip: Použite tento vzor, keď potrebujete vynútiť stav komponenty zvonka. Presuňte rekvizity komponentu na kontrolu jej interného stavu.
Príklad:
<!-- Modal.vue -->
<template>
<div v-if="isOpen" class="modal">
<div class="modal-content">
<slot></slot>
<button @click="closeModal">Zatvoriť</button>
</div>
</div>
</template>
<script setup>
defineProps({
isOpen: {
type: Boolean,
default: false
}
});
const emit = defineEmits(['close']);
function closeModal() {
emit('close');
}
</script>
<!-- Komponent rodiča -->
<template>
<div>
<button @click="showModal = true">Otvoriť modálny</button>
<Modal :isOpen="showModal" @close="showModal = false">
<p>Obsah modálnych</p>
</Modal>
</div>
</template>
<script setup>
import { ref } from 'vue';
import Modal from './Modal.vue';
const showModal = ref(false);
</script>
5. Metadáta komponentov
Pridajte metadáta komponentom na poskytnúť ďalšie informácie ostatným komponentom. To je možné použiť na konfiguráciu komponentov, na sto ďalších informácií alebo na uľahčenie komunikácie medzi komponentami.
Tip: Používajte metadáta na konfiguráciu komponentov alebo na sto ďalších informácií. To môže byť užitočné na nástroje alebo na poskytnúť kontext ostatným komponentom.
Príklad:
<!-- Komponent A -->
<template>
<div>Komponent A</div>
</template>
<script>
export default {
meta: {
componentType: 'display'
}
}
</script>
<!-- Komponent B -->
<template>
<div>Komponent B</div>
</template>
<script>
export default {
meta: {
componentType: 'formField'
}
}
</script>
Composable vzory dizajnu
1. Vzor objektu možnosti
Na prenos parametrov do composables používajte objekt. To umožňuje flexibilitu a škálovateľnosť. Je to preferovaný spôsob na prenos mnohých možností do composable.
Tip: Tento vzor sa používa v VueUse a je vrúcne odporúčaný, keď potrebujete nakonfigurujte správanie composable.
Príklad:
// useFetch.js
import { ref, onMounted } from 'vue';
export function useFetch(url, options = {}) {
const data = ref(null);
const loading = ref(false);
const error = ref(null);
const { method = 'GET', headers = {}, body = null } = options;
async function fetchData() {
loading.value = true;
try {
const response = await fetch(url, {
method,
headers,
body: body ? JSON.stringify(body) : null
});
if (!response.ok) {
throw new Error(`HTTP chyba! status: ${response.status}`);
}
data.value = await response.json();
} catch (e) {
error.value = e;
} finally {
loading.value = false;
}
}
onMounted(() => {
fetchData();
});
return { data, loading, error, fetchData };
}
// V komponente:
import { useFetch } from './useFetch';
export default {
setup() {
const { data, loading, error } = useFetch('/api/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: { key: 'value' }
});
return { data, loading, error };
}
}
2. Vrátené composables
Vytvárali composables priamo v súbore komponentu, aby ste sa vyhli vytváraní nových súborov. To je obzvlášť užitočné pre composables, ktoré sú veľmi špecifické pre jeden komponent a nie sú určené na opätovné použitie.
Používajte vrátené composables na malú, špecifickú logiku komponentov. To udržiava súvisiaci kód spolu a môže zjednodušiť štruktúru komponentov.
Tip: Používajte vrátené composables na malú, špecifickú logiku komponentov, ktorá nemá byť opakovane použitá. Tento prístup je skladá spolu s komponentom a zjednodušuje štruktúru komponentov.
Príklad:
Povedzme, že máte toto v svojom komponente:
<template>
<div>{{ formattedDate }}</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const useFormattedDate = () => {
const rawDate = ref(new Date())
const formattedDate = computed(() => {
const options = { year: 'numeric', month: 'long', day: 'numeric' }
return rawDate.value.toLocaleDateString(undefined, options)
})
return { formattedDate }
}
const { formattedDate } = useFormattedDate()
</script>
Je to v poriadku po teraz, ale ak budete potrebovať formátovanie dátumov kdekoľvek iinde, ste stratení. Tu je refaktorovaná verzia:
// src/composables/useFormattedDate.ts
import { ref, computed } from 'vue'
export function useFormattedDate() {
const rawDate = ref(new Date())
const formattedDate = computed(() => {
const options = { year: 'numeric', month: 'long', day: 'numeric' }
return rawDate.value.toLocaleDateString(undefined, options)
})
return { formattedDate }
}
<!-- Vo vašom komponente -->
<template>
<div>{{ formattedDate }}</div>
</template>
<script setup>
import { useFormattedDate } from './composables/useFormattedDate'
const { formattedDate } = useFormattedDate()
</script>
Teraz môžete opätovne používať useFormattedDate v ľubovoľnom komponente. Problém vyriešený.
3. Lepšie kódovanie Composables
Extrahovať malé kúsky logiky do funkcií, ktoré môžete ľahko opakovane používať. To podporuje opätovné používanie kódu, znižuje duplikácie a robí váš kód udržiavateľnejším.
Tip: Používajte composables na organizáciu a opätovné používanie obchodnej logiky. Myslite na composables ako na opätovne použiteľné stavebné bloky pre vašu aplikáciu.
Príklad:
// useLocalStorage.ts
import { ref, watch } from 'vue';
export function useLocalStorage<T>(key: string, defaultValue: T) {
const storedValue = localStorage.getItem(key);
const value = ref<T>(storedValue !== null ? JSON.parse(storedValue) : defaultValue);
watch(
value,
(newValue) => {
localStorage.setItem(key, JSON.stringify(newValue));
},
{ deep: true }
);
return value;
}
// Použitie v komponente:
<script setup>
import { useLocalStorage } from './useLocalStorage';
const theme = useLocalStorage('theme', 'light');
</script>
4. Začnite s rozhraním
Pred implementáciou definujte, ako sa composable bude používať. To je forma vývoja "dizajn-prvý", ktorá vám pomôže ujasniť účel composable, vstupy a výstupy pred napísaním akéhokoľvek kódu.
Tip: Definujte vstupy (rekvizity, možnosti) a výstupy (vrátené hodnoty) composable prvý. To vám pomôže zamerať sa na API composable.
Príklad:
// Pred implementáciou: useCounter.js
// Mal by akceptovať počiatočnú hodnotu
// Mal by vrátiť počet a metódy na prírasty a pokles
// Implementácia:
import { ref } from 'vue';
export function useCounter(initialValue = 0) {
const count = ref(initialValue);
function increment() {
count.value++;
}
function decrement() {
count.value--;
}
return { count, increment, decrement };
}
5. Opätovné použitie logiky s oblasťou sloty
Používajte oblasť sloty na opätovné používanie logiky medzi komponentami jedinečným spôsobom. Oblasť sloty umožňujú rodičovskému komponentu presunúť údaje a logiku do svojho dieťaťa, čo poskytuje flexibilný spôsob zdieľania funkcií.
Tip: Oblasť sloty je možné použiť na prenos údajov a logiky z rodičovského komponentu na dieťa. To umožňuje dieťaťu vykresliť svoj obsah na základe údajov a logiky poskytnutej rodiča.
Príklad:
<!-- DataFetcher.vue -->
<template>
<div>
<div v-if="loading">Načítavame...</div>
<div v-else-if="error">Chyba: {{ error }}</div>
<div v-else>
<slot :data="data" :loading="loading" :error="error"></slot>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const props = defineProps({
url: {
type: String,
required: true
}
});
const data = ref(null);
const loading = ref(true);
const error = ref(null);
onMounted(async () => {
try {
const response = await fetch(props.url);
if (!response.ok) {
throw new Error(`HTTP chyba! status: ${response.status}`);
}
data.value = await response.json();
} catch (e) {
error.value = e.message;
} finally {
loading.value = false;
}
});
</script>
<!-- Použitie v komponente -->
<DataFetcher url="/api/items">
<template v-slot="{ data, loading, error }">
<div v-if="loading">Načítavame položky...</div>
<div v-else-if="error">Chyba: {{ error }}</div>
<div v-else>
<ul>
<li v-for="item in data" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
</DataFetcher>
Všeobecný tips a najlepšie postupy
1. Ref vs. Reaktívna
Pochopte rozdiele medzi ref a reactive a vyberte si vhodný pre váš prípad použitia. ref sa používa na primárne hodnoty, zatiaľ čo reactive sa používa na objekty a polia.
Tip: Používajte
refna primárne hodnoty areactivena objekty a polia. To pomáha systému reaktivity Vue.
Príklad:
<script>
import { ref, reactive } from 'vue';
export default {
setup() {
const count = ref(0); // ref na primárnu hodnotu
const user = reactive({ name: 'John', age: 30 }); // reaktívny na objekt
return { count, user };
}
}
</script>
2. Efektívna správa stavu
Štruktúra stavu v aplikáciách efektívne. To je rozhodujúce na spravovanie toku údajov a zabezpečenie, aby vaša aplikácia zostala spravovateľná s rastúcou. Zvážte vhodné knižnice na správu stavu pre väčšie aplikácie.
Tip: Na správu stavu v väčšom aplikáciách zvážte Pinia alebo Vuex. Tieto knižnice poskytujú centralizovanú správu stavu a uľahčujú spravovanie zložitého stavu aplikácie.
Príklad: (Ilustratívne - skutočná implementácia závisí od zvolenej knižnice na správu stavu)
// Príklad Pinia (Konceptuálne)
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({
isLoggedIn: false,
user: null
}),
actions: {
login(userData) {
this.isLoggedIn = true;
this.user = userData;
},
logout() {
this.isLoggedIn = false;
this.user = null;
}
}
});
3. Používajte úvodné slová na sledovanie vnorených hodnôt
Sledujte vnorené hodnoty priamo pomocou úvodných slov. To umožňuje sledovanie zmien v špecifických vlastnostiach objektu, pričom sa spúšťajú aktualizácie pri zmene týchto vlastností.
Tip: Používajte úvodné slová v možnosti
watchna sledovanie vnorených vlastností objektu. To je efektívnejší a špecifickejší spôsob na sledovanie zmien.
Príklad:
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const data = ref({ user: { name: 'John' } });
watch(() => data.value.user.name, (newName) => {
console.log('Meno sa zmenilo:', newName);
});
return { data };
}
}
</script>
4. Vzor extrakcie podmieneného textu
Rozdelite komponenty podľa podmienenej logiky. To zlepšuje čitateľnosť a udržiavateľnosť tým, že oddelí opatrenia. Robí komponenty zrozumiteľnejšími a testovateľnými.
Tip: Ak má komponent zložitú podmienenú logiku, zvážte jej rozdelenie do menších komponentov. To vytvára zameranejšie a spravovateľnejšie komponenty.
Príklad:
<!-- Pred: Zložitá podmienená logika -->
<template>
<div>
<div v-if="isLoading">Načítavame...</div>
<div v-else-if="error">Chyba: {{ error }}</div>
<div v-else>
<UserList v-if="users.length > 0" :users="users" />
<NoUsersMessage v-else />
</div>
</div>
</template>
<!-- Po: Použitie extrahu komponentov -->
<template>
<LoadingIndicator v-if="isLoading" />
<ErrorMessage v-if="error" :message="error" />
<UsersDisplay v-else :users="users" />
</template>
5. 6 dôvodov na rozdelenie komponentov
Rozdeľte komponenty na menšie časti na zlepšenie organizácie kódu a opätovného použitia. To zvyšuje čitateľnosť, udržiavateľnosť a testovateľnosť vášho kódu.
Tip: Menšie komponenty sú ľahšie na pochopenie, testovanie a údržbu. Podporujú aj opätovné použitie, keďže ich môžete používať v rôznych častiach aplikácie.
Príklad:
<!-- Pred: Monolitický komponent -->
<template>
<div>
<Header />
<Sidebar />
<MainContent />
<Footer />
</div>
</template>
<!-- Po: Použitie extrahu komponentov -->
<template>
<AppLayout>
<template v-slot:header><Header /></template>
<template v-slot:sidebar><Sidebar /></template>
<template v-slot:main><MainContent /></template>
<template v-slot:footer><Footer /></template>
</AppLayout>
</template>
6. Neprepíšte komponenty CSS
Vyhnite sa priamej úprave CSS komponenty zvonka. To môže viesť k neočakávanému správaniu a sťažuje údržbu štýlov vašej aplikácie. Zapúzdrite štýly v samotnom komponente.
Tip: Používajte rekvizity alebo sloty na úpravu vzhľadu komponentu. To umožňuje kontrolované štýlovanie a zabezpečuje, že sa zabráni neočakávaným konfliktom štýlu.
Príklad:
<!-- Button.vue -->
<template>
<button :class="['button', variant]" @click="emit('click')">
<slot></slot>
</button>
</template>
<script setup>
const props = defineProps({
variant: {
type: String,
default: 'primary'
}
});
const emit = defineEmits(['click']);
</script>
<style scoped>
.button {
/* Základné štýly tlačidla */
}
.primary {
/* Primárne štýly tlačidla */
}
.secondary {
/* Sekundárne štýly tlačidla */
}
</style>

