13/12/2025
Skab Din Egen Mobilswipper i React: En Dybdegående Guide
I en tid hvor mobiladgang til internettet er altafgørende, er det essentielt at sikre, at dine webapplikationer fungerer gnidningsfrit på tværs af enheder, især på Android og iPhones. En af de mest udfordrende aspekter ved mobilwebudvikling er at implementere intuitiv navigation, og især "swiping"-bevægelser kan give udviklere grå hår. Mens der findes adskillige biblioteker, der kan hjælpe med denne opgave, hvad nu hvis du kunne bygge din egen, skræddersyede løsning? Denne artikel vil guide dig igennem processen med at skabe en mobil swiping-komponent i React med imponerende 50 linjer JavaScript.

Denne komponent blev oprindeligt udviklet til et personligt projekt, et 2048-spil i React, og nu deler jeg processen med jer. Hvis du vil prøve resultatet før du dykker ned i koden, kan du spille spillet [indsæt link til spil her]. I denne tutorial fokuserer vi udelukkende på selve mobilswiping-funktionaliteten.
Du kan finde de relevante ressourcer på GitHub: [indsæt link til GitHub her]. Her er et lille smugkig på funktionaliteten (kvaliteten er måske ikke perfekt, da jeg prioriterede filstørrelse): [indsæt GIF eller billede af funktionalitet her].
Forudsætninger
Før vi går i gang, er det vigtigt at have en grundlæggende forståelse for React og JavaScript. Du behøver ikke avancerede værktøjer, men hvis du vil køre eksemplet lokalt, skal du have Node.js installeret. Til denne tutorial bruger jeg Google Chrome til at simulere en mobil enhed på min computer. Vær opmærksom på, at trinene kan variere en smule afhængigt af din browser.
Sådan Simulerer Du en Mobil Enhed i Din Browser
Inden vi kaster os over koden, er det nødvendigt at vide, hvordan man simulerer en mobil enhed i Google Chrome. Følg disse trin:
- Åbn din browser, højreklik på siden, og vælg "Inspect" (Undersøg) i dropdown-menuen.
- Chrome Developer Tools vil nu åbne. Klik på ikonet med en bærbar computer og en mobiltelefon øverst til venstre i Developer Tools.
- Vælg derefter "Dimensions" (Dimensioner) for den enhed, du ønsker at simulere. Jeg har valgt iPhone SE, da den har en af de mindste understøttede opløsninger for mit spil.
Nu er du klar til at simulere swiping ved hjælp af din mus eller touchpad. Læg mærke til, hvordan markøren forvandles til en cirkel, der visualiserer brugerens fingerområde. Når du forsøger at swipe, opfatter browseren det som en almindelig scrolling af websiden. Dette er dog ikke den ønskede adfærd i vores tilfælde; vi vil bruge swipes til at styre spillet.
Standard browseradfærd associerer scrolling med swipe-bevægelser.
The MobileSwiper Komponent
Lad os starte med at oprette en fil kaldet mobile-swiper.jsx. Her definerer vi en standard React-komponent. Vores komponent skal acceptere to egenskaber (props): children og onSwipe.
export default function MobileSwiper ( { children, onSwipe } ) { return null; } Lad os kort forklare disse props:
children: TilladerMobileSwiperat modtage og rendere alt indhold, der placeres mellem dens åbnings- og lukketags. Dette giver dig mulighed for at indsætte hele spilbrættet i denne komponent.onSwipe: En callback-funktion, som vores komponent vil kalde, hver gang brugeren udfører en swipe-bevægelse inden for det definerede "swipable" område.
Nu skal vi definere det område, hvor swiping skal registreres. Først skal vi tilføje en reference til DOM-elementet, hvor vi vil tillade swiping. Dette gøres ved hjælp af useRef hooken. Lad os deklarere en konstant kaldet wrapperRef:
import { useRef } from "react"; export default function MobileSwiper ( { children, onSwipe } ) { const wrapperRef = useRef( null ); return null; } Sidebemærkning: useRef er en React Hook, der giver dig mulighed for at referere til en værdi, der ikke er nødvendig for rendering. Det bruges ofte til at manipulere DOM'en, og React har indbygget understøttelse for dette.
Nu skal vi blot returnere en <div />, der refererer til den konstant, vi lige har oprettet:
import { useRef } from "react"; export default function MobileSwiper ( { children, onSwipe } ) { const wrapperRef = useRef( null ); return ( {children} ); } Lad os nu overveje, hvordan vi kan detektere en swipe-bevægelse. Den nemmeste metode er at sammenligne start- og slutpositionen for brugerens finger. Dette betyder, at vi skal gemme brugerens startposition i state. Vi vil bruge useState hooken til at gemme x- og y-koordinaterne.
import { useState, useRef } from "react"; export default function MobileSwiper ( { children, onSwipe } ) { const wrapperRef = useRef( null ); const [startX, setStartX] = useState( 0 ); const [startY, setStartY] = useState( 0 ); return ( {children} ); } Nu skal vi oprette to event callbacks:
handleTouchStart: Sætter startpositionen for brugerens finger.handleTouchEnd: Sætter slutpositionen for brugerens finger og beregner forskellen (delta) baseret på startpunktet.
Lad os starte med handleTouchStart event handleren:
import { useCallback, useState, useRef } from "react"; export default function MobileSwiper ( { children, onSwipe } ) { const wrapperRef = useRef( null ); const [startX, setStartX] = useState( 0 ); const [startY, setStartY] = useState( 0 ); const handleTouchStart = useCallback( ( e ) => { if (!wrapperRef.current.contains(e.target)) { return; } e.preventDefault(); setStartX(e.touches[0].clientX); setStartY(e.touches[0].clientY); }, []); return ( {children} ); } Lad mig kort forklare denne funktion:
- Funktionen er pakket ind i
useCallbackhooken for at cache og forbedre dens ydeevne. Hvis du ikke kender denne hook, kan du læse mere om den i den officielle React-dokumentation. if-sætningen tjekker, om brugeren swiper inden for det definerede swipe-område. Hvis de swiper uden for dette område, fortsætter vi med standard scrolling.e.preventDefault()deaktiverer standard scrolling-eventet.- De sidste to linjer gemmer x- og y-koordinaterne i state.
Lad os nu implementere handleTouchEnd event handleren:
import { useCallback, useState, useRef } from "react"; export default function MobileSwiper ( { children, onSwipe } ) { const wrapperRef = useRef( null ); const [startX, setStartX] = useState( 0 ); const [startY, setStartY] = useState( 0 ); const handleTouchStart = useCallback( ( e ) => { if (!wrapperRef.current.contains(e.target)) { return; } e.preventDefault(); setStartX(e.touches[0].clientX); setStartY(e.touches[0].clientY); }, []); const handleTouchEnd = useCallback( ( e ) => { if (!wrapperRef.current.contains(e.target)) { return; } e.preventDefault(); const endX = e.changedTouches[0].clientX; const endY = e.changedTouches[0].clientY; const deltaX = endX - startX; const deltaY = endY - startY; onSwipe({ deltaX, deltaY }); }, [startX, startY, onSwipe]); return ( {children} ); } Som du kan se, er trin 1-3 identiske med handleTouchStart callbacken. Nu tager vi de endelige x- og y-koordinater for brugerens finger og trækker de oprindelige x- og y-værdier fra dem. Dette giver os mulighed for at beregne den horisontale og vertikale forskydning af brugerens finger (deltas). Derefter sender vi disse deltas videre til onSwipe callbacken, som vi definerede i komponentens props tidligere.
Nu skal vi forbinde disse callbacks til event listeners. Dette kan gøres ved hjælp af useEffect hooken fra React.
import { useCallback, useEffect, useState, useRef } from "react"; export default function MobileSwiper ( { children, onSwipe } ) { const wrapperRef = useRef( null ); const [startX, setStartX] = useState( 0 ); const [startY, setStartY] = useState( 0 ); const handleTouchStart = useCallback( ( e ) => { if (!wrapperRef.current.contains(e.target)) { return; } e.preventDefault(); setStartX(e.touches[0].clientX); setStartY(e.touches[0].clientY); }, []); const handleTouchEnd = useCallback( ( e ) => { if (!wrapperRef.current.contains(e.target)) { return; } e.preventDefault(); const endX = e.changedTouches[0].clientX; const endY = e.changedTouches[0].clientY; const deltaX = endX - startX; const deltaY = endY - startY; onSwipe({ deltaX, deltaY }); }, [startX, startY, onSwipe]); useEffect(() => { window.addEventListener("touchstart", handleTouchStart); window.addEventListener("touchend", handleTouchEnd); return () => { window.removeEventListener("touchstart", handleTouchStart); window.removeEventListener("touchend", handleTouchEnd); }; }, [handleTouchStart, handleTouchEnd]); return ( {children} ); } Du kan læse mere om useEffect hooken i den officielle React-dokumentation. Nu er MobileSwiper komponenten klar.
Lad Os Gøre Det Swipable
Det sidste vi skal gøre, er at integrere vores komponent i applikationen. Som nævnt vil jeg bruge denne komponent i mit 2048-spil (kildekode her: [indsæt link til kildekode her]). Hvis du vil bruge den et andet sted, vil handleSwipe hjælpefunktionen og MobileSwiper komponenten forblive de samme.
Lad os integrere den i Board komponenten:
import { useCallback, useContext, useEffect, useRef } from "react"; import { Tile as TileModel } from "@/models/tile"; import styles from "@/styles/board.module.css"; import Tile from "./tile"; import { GameContext } from "@/context/game-context"; import MobileSwiper from "./mobile-swiper"; export default function Board() { const { getTiles, moveTiles, startGame } = useContext(GameContext); const handleSwipe = useCallback( ({ deltaX, deltaY }) => { if (Math.abs(deltaX) > Math.abs(deltaY)) { if (deltaX > 0) { moveTiles("move_right"); } else { moveTiles("move_left"); } } else { if (deltaY > 0) { moveTiles("move_down"); } else { moveTiles("move_up"); } } }, [moveTiles] ); return ( {renderTiles()}{renderGrid()} ); } Lad os starte med handleSwipe handleren. Som du kan se, sammenligner vi, om deltaX er større end deltaY for at bestemme, om brugeren swipede horisontalt (venstre/højre) eller vertikalt (top/bund).
- Hvis det var en horisontal swipe:
- Negativ
deltaXbetyder, at de swipede til venstre. - Positiv
deltaXbetyder, at de swipede til højre.
- Negativ
- Hvis det var en vertikal swipe:
- Negativ
deltaYbetyder, at de swipede op. - Positiv
deltaYbetyder, at de swipede ned.
- Negativ
Lad os nu fokusere på MobileSwiper komponenten. Du kan finde den i return-udsagnet. Vi passerer handleSwipe hjælperfunktionen til onSwipe egenskaben og pakker hele HTML-koden for Board komponenten ind for at aktivere swiping på den.
Når vi tester dette nu, er resultatet ikke ideelt. Scrolling-events blandes med mobil-swipes, som du kan se her: [indsæt billede af duplikerede events her]. Dette sker, fordi moderne browsere bruger passive event listeners for at forbedre scrolling-oplevelsen på mobile enheder. Det betyder, at preventDefault, som vi tilføjede til vores event callbacks, aldrig bliver aktiveret. For at deaktivere scrolling-adfærd skal vi deaktivere passive listeners på MobileSwiper komponenten:
import { useCallback, useEffect, useState, useRef } from "react"; export default function MobileSwiper ( { children, onSwipe } ) { // ... (resten af koden er den samme) useEffect(() => { window.addEventListener("touchstart", handleTouchStart, { passive: false }); window.addEventListener("touchend", handleTouchEnd, { passive: false }); return () => { window.removeEventListener("touchstart", handleTouchStart); window.removeEventListener("touchend", handleTouchEnd); }; }, [handleTouchStart, handleTouchEnd]); // ... (resten af koden er den samme) } Nu er scrolling-adfæren forsvundet, og 2048-spillet ser fantastisk ud: [indsæt billede af det endelige resultat her].
Opsummering
I dag har jeg vist dig, at du ikke altid behøver biblioteker for at håndtere mobile gestures i React. Simple events som swiping kan implementeres ved hjælp af grundlæggende React-funktioner. Vi brugte blot en række React hooks og skrev to simple event handlers. Hele implementeringen består af præcis 50 linjer kode. Jeg håber, at jeg har inspireret dig til selv at prøve kræfter med mobile events.
Hvis denne artikel har været til hjælp, så lad mig det gerne vide på Twitter. Undervisere som mig føler sig ofte som om, de taler ud i et vakuum, og at ingen bekymrer sig om, hvad de underviser. Et simpelt "shoutout" viser, at det var indsatsen værd og inspirerer mig til at skabe mere indhold som dette. Del venligst denne artikel på dine sociale medier. Tak!
Lav Dit Eget 2048-spil
Denne artikel er en del af mit kursus på Udemy, hvor jeg underviser i, hvordan man laver et fuldt funktionelt 2048-spil i Next.js fra bunden. Tilmeld dig mit Next.js-kursus på Udemy. Brug koden FREECODECAMP for at få 60% rabat.
Jeg tror på, at programmering skal være sjovt og frigøre kreativitet. Du behøver ikke bygge endnu en TODO-liste eller en indkøbskurv. I stedet kan du bygge noget, du kan vise dine venner eller måske en potentiel arbejdsgiver!
PS. Hvis du foretrækker at se screencasts, er denne lektion tilgængelig gratis på Udemy. Du kan finde den under sektionen "Responsive Layout and Missing Game Feature" i forelæsningen kaldet "Game layout and mobile swipes".
Sammenligning: Onswipe vs. Children i MobileSwiper
Det er vigtigt at forstå forskellen mellem de to primære props, vi bruger i vores MobileSwiper komponent: children og onSwipe.
children
children er en standard React prop, der giver komponenter mulighed for at acceptere og rendere andre komponenter eller DOM-elementer, som er placeret imellem deres åbnings- og lukketags. I vores tilfælde bruger vi {children} inde i MobileSwiper komponenten til at omslutte det indhold, som brugeren ønsker at gøre swipe-venligt. Det kan være et spilbræt, en billedkarusel, eller enhver anden UI-komponent. Dette gør MobileSwipergenanvendelig og fleksibel, da den ikke er bundet til en specifik type indhold.
onSwipe
onSwipe er en callback-funktion, som vi specifikt har defineret for vores MobileSwiper komponent. Denne prop modtager en funktion som værdi. Hver gang en gyldig swipe-bevægelse detekteres inden for det definerede område, kalder MobileSwiper denne funktion og sender et objekt med deltaX og deltaY værdierne med som argumenter. Det er op til den komponent, der bruger MobileSwiper (f.eks. vores 2048-spil), at definere, hvad der skal ske, når en swipe registreres. Dette decoupler swipe-detektionen fra den specifikke handling, der skal udføres, hvilket igen øger komponentens genanvendelighed og gør det nemmere at håndtere forskellige swipe-interaktioner.
Tabeloversigt:
| Prop | Type | Formål | Eksempel på Brug |
|---|---|---|---|
children | React Nodes | Modtager og viser indholdet, der er placeret inde i <MobileSwiper></MobileSwiper> tags. | <MobileSwiper><MyGameContent /></MobileSwiper> |
onSwipe | Callback Funktion | Udføres, når en swipe detekteres. Modtager swipe-detaljer (deltaX, deltaY). | <MobileSwiper onSwipe={handleGameMove}> |
Ofte Stillede Spørgsmål (FAQ)
Hvad er forskellen på children og onSwipe i MobileSwiper?
children bruges til at indsætte det indhold, der skal være swipe-bart (f.eks. et spilbræt). onSwipe er en funktion, der kaldes, når en swipe-bevægelse registreres, og den giver information om swipens retning og styrke.
Kan jeg bruge MobileSwiper til andet end spil?
Absolut! Da MobileSwiper bruger children, kan den omslutte ethvert React-komponent. Du kan bruge den til at lave swipe-bare gallerier, navigationsmenuer, eller enhver anden komponent, der drager fordel af swipe-interaktioner.
Hvorfor er passive: false vigtigt?
passive: false er afgørende for at kunne overskrive browserens standardadfærd, såsom scrolling, når en swipe-bevægelse detekteres. Uden dette ville browseren ofte prioritere scrolling-eventet, hvilket forhindrer din swipe-logik i at blive udført korrekt.
Hvordan bestemmer jeg retningen af swipen?
Ved at sammenligne deltaX og deltaY. Hvis Math.abs(deltaX) er større end Math.abs(deltaY), var swipen primært horisontal. Hvis deltaX er positiv, swiped der til højre; hvis den er negativ, swiped der til venstre. Omvendt, hvis Math.abs(deltaY) er større, var swipen primært vertikal. Positiv deltaY indikerer en swipe nedad, og negativ indikerer en swipe opad.
Hvis du vil læse andre artikler, der ligner Lav din egen mobilswipper i React, kan du besøge kategorien Teknologi.
