Oprydning af JavaScript-kode: hvordan du kan reflektere for at bruge klasser
I mindre React-projekter fungerer det godt at opbevare alle dine komponentmetoder i selve komponenterne. I mellemstore projekter vil du måske ønske, at du kunne få disse metoder ud af dine komponenter og ind i en "hjælper". Her viser jeg dig, hvordan du bruger en klasse (i stedet for at eksportere individuelle funktioner og variabler) til at organisere din kode.
Bemærk : Jeg arbejder i React, så det er eksemplet, vi diskuterer her.
Typisk refaktor
I en typisk refaktor tager du en funktion på komponenten og flytter den til en anden hjælper.
Fra:
const MyComponent = () => { const someFunction = () => 'Hey, I am text' return ( {someFunction()} ) }
Til:
import { someFunction } from 'functionHelper.js' const MyComponent = () => { return ( {someFunction()} ) }
og
export const someFunction = () => 'Hey, I am text'
Dette eksempel er virkelig fjollet, men du kan se, hvor vi skal hen:
- Tag dine funktioner, og kopier dem til en separat fil
- Importer dem, og kald dem som normalt.
Når tingene bliver komplicerede, skal du dog videregive en masse ting til disse funktioner - objekter, funktioner til manipulation af tilstand osv. I dag løb jeg ind i et problem, hvor jeg ønskede at udtrække tre funktioner ud af en komponent, og de krævede alle de samme indgange (a resource
og en funktion til at opdatere resource
). Der må være en bedre måde ...
Refactoring med en klasse
Jeg lavede en stor demo til dette indlæg. Du kan se koden på Github. Den oprindelige forpligtelse viser al funktionalitet inde i hovedkomponenten ( App.js
), og den efterfølgende forpligter refaktor til koden for at bruge en klasse.

Du kan køre dette selv og gøre hvad du vil. Husk at yarn install
.
Vi starter med en komponent, der "henter" et objekt (efterligner den måde, vi kan gøre dette på fra en API) med visse attributter på det: gentag (antal felter), side (højde og bredde), tekst, farve. Vi har derefter en række måder, vi manipulerer visningen på - at ændre farve, opdatere teksten osv. Efter hver ændring viser vi en besked.
For eksempel er her vores ændringsbredde og højdemetode:
changeSide = side => { const obj = {...this.state.obj, side} this.fetchObject(obj); this.setState({ message: `You changed the sides to ${side} pixels!` }); }
Vi kan have en række andre metoder, der kræver lignende handlinger - eller måske meget forskellige metoder. Vi begynder måske at tænke på at udtrække denne kode til en hjælper. Derefter ville vi oprette en anden metode til at kalde setState
handlingen, og vi skulle videregive den, this.fetchObject
objektet i tilstand, og det side
vi får som et argument til metoden. Hvis vi har flere lignende metoder, er det en masse passerende parametre, og måske er det faktisk ikke så nyttigt (eller læsbart).
I stedet kan vi bruge en klasse komplet med en konstruktormetode:
export default class ObjectManipulator { constructor( { object, fetchObject, markResettable, updateMessage, updateStateValue } ) { this.fetchObject = fetchObject; this.markResettable = markResettable; this.updateMessage = updateMessage; this.updateStateValue = updateStateValue; } changeSide = ( object, side ) => { const newObject = { ...object, side }; this.fetchObject(newObject); this.updateMessage(`You changed the sides to ${side} pixels!`); this.markResettable(); this.updateStateValue('side', side); }; };
Dette giver os mulighed for at oprette et objekt, hvis funktioner vi kan kalde inde i vores hovedkomponent:
const manipulator = new ObjectManipulator({ object, fetchObject: this.fetchObject, markResettable: this.markResettable, updateMessage: this.updateMessage, updateStateValue: this.updateStateValue, });
Dette skaber et objekt manipulator
- en forekomst af vores ObjectManipulator
klasse. Når vi kalder manipulator.changeSide(object, '800')
det, kører den changeSide
metode, vi definerer ovenfor. Der er ingen grund til at videregive updateMessage
eller nogen af de andre metoder - vi henter dem fra konstruktøren, da vi oprettede forekomsten.
Du kan forestille dig, at dette bliver virkelig nyttigt, hvis vi har mange af disse metoder at håndtere. I mit tilfælde havde jeg brug for at ringe til .then(res => myFunction(r
es) efter alt det, jeg prøvede at udtrække. Defini ng myFunct
ion på klasseinstansen i stedet for at sende den til hver funktion sparede mig en masse kode.
At holde alt organiseret
Denne organisationsmetode kan være virkelig nyttigt at holde alt på plads. For eksempel har jeg en række farver, som jeg kortlægger for at få de farveknapper, du ser i eksemplet. Ved at flytte denne konstant ind i ObjectManipulator
, kan jeg sørge for, at den ikke kolliderer med nogen anden colors
i resten af min app:
export default class ObjectManipulator { [...] colors = ['blue', 'red', 'orange', 'aquamarine', 'green', 'gray', 'magenta']; };
Jeg kan bruge manipulator.colors
til at få fat i de rigtige farver til denne side, hvorimod der muligvis er en global colors
konstant, der bruges til noget andet.
Referencer
Gode gamle Mozilla Class-dokumenter