I programmering er det grunnleggende å organisere kode på en måte som fremmer gjenbruk. Duplisering av kode kan føre til at kodebasen vokser seg stor og vanskelig å håndtere, spesielt i omfattende applikasjoner.
Vue forenkler kode gjenbruk med hjelp av *composables*. Dette er funksjoner som samler sammen logikk, og kan benyttes på nytt i hele prosjektet for å håndtere repeterende oppgaver.
Var det alltid Composables?
Før introduksjonen av *composables* i Vue 3, var det vanlig å benytte *mixins* for å oppnå kode gjenbruk i ulike deler av applikasjonen. *Mixins* inneholdt Vue.js-spesifikke elementer som data, metoder, og livssyklus-hooks, som tillot gjenbruk av kode i flere komponenter.
For å opprette en *mixin*, organiserte man koden i separate filer som deretter ble brukt i komponenter ved å legge til *mixin* til *mixins*-egenskapen i komponentens *options* objekt. For eksempel:
export const formValidationMixin = { data() { return { formData: { username: '', password: '', }, formErrors: { username: '', password: '', }, }; }, methods: { validateForm() { this.formErrors = {}; if (!this.formData.username.trim()) { this.formErrors.username="Username is required."; } if (!this.formData.password.trim()) { this.formErrors.password = 'Password is required.'; } return Object.keys(this.formErrors).length === 0; }, }, };
Dette kodeutdraget demonstrerer en *mixin* for skjema validering. Den inkluderer to dataegenskaper, `formData` og `formErrors`, som innledningsvis er satt til tomme verdier.
`formData` lagrer brukerinndata fra skjemaet, som brukernavn og passord. `formErrors` har en lignende struktur for å lagre feilmeldinger og er også tom fra starten.
Videre definerer *mixin* en metode, `validateForm()`, for å verifisere at både brukernavn- og passordfeltene inneholder verdi. Hvis et felt er tomt, fylles `formErrors` med en tilhørende feilmelding.
Metoden returnerer `true` om skjemaet er gyldig og `formErrors` er tom. For å benytte *mixin*, importeres den til Vue-komponenten og inkluderes i *mixin* egenskapen av Options-objektet:
<template> <div> <form @submit.prevent="submitForm"> <div> <label for="username">Username:</label> <input type="text" id="username" v-model="formData.username" /> <span class="error">{{ formErrors.username }}</span> </div> <div> <label for="password">Password:</label> <input type="password" id="password" v-model="formData.password" /> <span class="error">{{ formErrors.password }}</span> </div> <button type="submit">Submit</button> </form> </div> </template> <script> import { formValidation } from "./formValidation.js"; export default { mixins: [formValidation], methods: { submitForm() { if (this.validateForm()) { alert("Form submitted successfully!"); } else { alert("Please correct the errors in the form."); } }, }, }; </script> <style> .error { color: red; } </style>
Dette eksempelet viser en Vue-komponent opprettet med *Options API*. *Mixins* -egenskapen inneholder alle importerte mixins. I dette tilfellet benytter komponenten `validateForm` metoden fra *formValidation* mixin for å informere brukeren om utfallet av skjemainnsendingen.
Hvordan benytte Composables
En *composable* er en uavhengig JavaScript-fil med funksjoner som er spesifikt laget for å løse et bestemt behov. I en *composable* kan du utnytte Vue’s *Composition API* og benytte funksjoner som `refs` og `computed refs`.
Med tilgang til Composition API, kan du opprette funksjoner som kan benyttes i flere komponenter. Disse funksjonene returnerer et objekt, som enkelt kan importeres og benyttes i Vue-komponenter gjennom `setup`-funksjonen til Composition API.
For å ta i bruk en *composable*, opprett en ny JavaScript-fil i prosjektets `src`-katalog. I større prosjekter, bør du vurdere å organisere filene i en egen mappe, og lage separate JavaScript-filer for hver *composable* for å tydeliggjøre funksjonaliteten.
I JavaScript-filen definerer du den nødvendige funksjonen. Nedenfor er en restrukturering av *formValidation*-mixinen som en *composable*:
import { reactive } from 'vue'; export function useFormValidation() { const state = reactive({ formData: { username: '', password: '', }, formErrors: { username: '', password: '', }, }); function validateForm() { state.formErrors = {}; if (!state.formData.username.trim()) { state.formErrors.username="Username is required."; } if (!state.formData.password.trim()) { state.formErrors.password = 'Password is required.'; } return Object.keys(state.formErrors).length === 0; } return { state, validateForm, }; }
Dette kodeutdraget begynner med å importere `reactive` funksjonen fra *vue*-pakken. Deretter opprettes en eksporterbar funksjon, `useFormValidation()`.
Videre opprettes en reaktiv variabel, `state`, som inneholder egenskapene `formData` og `formErrors`. Koden håndterer deretter skjemavalideringen på en lignende måte som mixinen. Til slutt returneres `state`-variabelen og `validateForm` funksjonen som et objekt.
Du kan ta i bruk denne *composable* ved å importere JavaScript-funksjonen fra filen i komponenten din:
<template> <div> <form @submit.prevent="submitForm"> <div> <label for="username">Username:</label> <input type="text" id="username" v-model="state.formData.username" /> <span class="error">{{ state.formErrors.username }}</span> </div> <div> <label for="password">Password:</label> <input type="password" id="password" v-model="state.formData.password" /> <span class="error">{{ state.formErrors.password }}</span> </div> <button type="submit">Submit</button> </form> </div> </template> <script setup> import { useFormValidation } from "./formValidation.js"; import { ref } from "vue"; const { state, validateForm } = useFormValidation(); const submitForm = () => { if (validateForm()) { alert("Form submitted successfully!"); } else { alert("Please correct the errors in the form."); } }; </script> <style> .error { color: red; } </style>
Etter å ha importert `useFormValidation` *composable*, destructuring koden JavaScript-objektet den returnerer og fortsetter skjemavalideringen. Den varsler om skjemaet er vellykket innsendt eller om det er feil.
Composables er de nye Mixins
Mens *mixins* var nyttige i Vue 2 for kode gjenbruk, har *composables* tatt deres plass i Vue 3. *Composables* tilbyr en mer strukturert og vedlikeholdsvennlig tilnærming for gjenbruk av logikk i Vue.js applikasjoner, som gjør det enklere å skape skalerbare web-applikasjoner med Vue.