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:

  1. Tag dine funktioner, og kopier dem til en separat fil
  2. 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 resourceog 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 setStatehandlingen, og vi skulle videregive den, this.fetchObjectobjektet i tilstand, og det sidevi 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 ObjectManipulatorklasse. Når vi kalder manipulator.changeSide(object, '800')det, kører den changeSidemetode, vi definerer ovenfor. Der er ingen grund til at videregive updateMessageeller 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(res) efter alt det, jeg prøvede at udtrække. Defini ng myFunction 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 colorsi resten af ​​min app:

export default class ObjectManipulator { [...] colors = ['blue', 'red', 'orange', 'aquamarine', 'green', 'gray', 'magenta']; };

Jeg kan bruge manipulator.colorstil at få fat i de rigtige farver til denne side, hvorimod der muligvis er en global colorskonstant, der bruges til noget andet.

Referencer

Gode ​​gamle Mozilla Class-dokumenter