Da React Native ble kunngjort, var de første reaksjonene overveldende positive. Tradisjonelt, når vi tenker på webteknologier i mobilområdet, ting som Apache Cordova våren, som tillater oss å pakke nettsteder eller webapplikasjoner som applikasjoner for mobile plattformer. I denne nybegynnerveiledningen vil vi ta en titt på React Natives arkitektur, filosofien bak React Native, og hvordan den skiller seg fra andre løsninger i samme rom. Mot slutten av artikkelen vil vi ha forvandlet en React “Hello World” -applikasjon til en React Native.
La oss starte med å si det Reager Native er en relativt ny teknologi. Den har vært offisielt tilgjengelig siden mars 2015, etter å ha vært i privat beta siden starten av det året, og brukt internt på Facebook en stund før det. Ordtaket 'Roma ble ikke bygget på en dag' gjelder generelt også teknologi. Verktøy som grunt
og plattformer som Node.js tok år å modnes. I nettverdenen beveger ting seg raskt, og med et stort antall rammer, pakker og verktøy som kommer ut hver dag, utviklere har en tendens til å bli litt mer skeptisk og vil ikke hoppe på hver sprøytevogn bare for å innse at de havnet i en leverandørsperre. Vi vil komme inn på hva som gjør React Native spesiell, hvorfor det er en teknologi det er verdt å komme inn på, og dekke noen få tilfeller der det ikke er alle enhjørninger og regnbuer.
Når vi snakker om webteknologier på mobil, faller tilgjengelige løsninger vanligvis inn i en av følgende kategorier.
Nettapplikasjonen lever i en mobil nettleser, vanligvis kalt WebView. Uten større refactoring fungerer et nettsted eller en webapplikasjon på den mobile enheten. Vi må kanskje vurdere mobile nettleserhendelser som å tappe eller lytte til endringer i enhetsretning og den mindre skjermen for en komplett brukeropplevelse, men vi har en fungerende mobilversjon med minimal innsats. Cordova / PhoneGap er det mest populære alternativet i denne kategorien. Dessverre har dette alternativet en stor ulempe: i noen tilfeller er applikasjoner utviklet med Cordova betydelig langsommere enn innfødte applikasjoner, spesielt for grafisk tunge applikasjoner. I andre tilfeller tilbyr ikke mobiloperativsystemet alle funksjonene i WebView som er tilgjengelige i mobilnettleseren. Brukeropplevelsen kan også avvike fra innfødte applikasjoner; dette kan skje på grunn av applikasjonen eller selve plattformen. Dette problemet kan variere fra rullefelt som ikke føler det samme til å ha en merkbar forsinkelse når du tapper på elementer.
En helt annen løsning er å lage en innfødt kodebase til slutt. Dette skjer ved å transformere den opprinnelige kildekoden til et annet programmeringsspråk. Vi bytter inn originale ytelser for et abstraksjonslag med noen usikkerheter. I tilfeller av lukkede kildeløsninger er vi ikke engang sikre på hva som skjer under panseret og med hva slags sort boks vi har å gjøre med. I andre tilfeller er vi ikke sikre på hvor mye den neste mobile operativsystemoppdateringen vil bryte koden vår, og når reparasjoner eller oppdateringer vil være tilgjengelige. Et populært eksempel på denne kategorien vil være Haxe .
Her bruker vi JavaScript-motoren i mobilmiljøet og utfører JavaScript der. Innfødte kontroller er kartlagt til JavaScript-objekter og funksjoner, så når vi skulle kalle en funksjon som heter fancyButtonRightHere()
, ville det vises en knapp på skjermen. NativeScript eller Appcelerator Titanium er kjente eksempler på denne kategorien.
React Native kan klassifiseres som noe fra den tredje kategorien. For iOS- og Android-versjonene bruker React Native JavaScriptCore under panseret, som er standard JavaScript-motor på iOS. JavaScriptCore er også JavaScript-motoren i Apples Safari-nettlesere. OS X og iOS-utviklere kan faktisk direkte grensesnitt med det hvis de vil.
En stor forskjell er at Reager Native kjører JavaScript-koden i en egen tråd, slik at brukergrensesnittet ikke blokkeres, og animasjoner skal være silkemyke og glatte.
Det er verdt å merke seg at 'Reager' i React Native ikke blir plassert der ved et uhell. For React Native trenger vi en forståelse av hva React akkurat tilbyr. Følgende konsepter fungerer det samme i både React og React Native, selv om disse kodeeksemplene er skreddersydd for å kjøres i nettleseren.
Når vi ser på en enkel React-komponent, er det første vi kan legge merke til at komponenten har en render
funksjon. Faktisk kaster React en feil hvis det ikke er definert noen gjengivelsesfunksjon inne i komponenten.
var MyComponent = function() { this.render = function() { // Render something here }; };
Det spesielle er at vi ikke roter med DOM-elementer her, men vi returnerer en XML-basert konstruksjon som representerer det som skal gjengis i DOM. Denne XML-baserte konstruksjonen kalles JSX.
var MyComponent = function() { this.render = function() { return Hello there ; }; };
En spesiell JSX-transformator tar all den XML-koden og konverterer den til funksjoner. Slik ser komponenten ut etter transformasjonen:
var MyComponent = function() { this.render = function() { return React.createElement('div', { className: 'my-component' }, 'Hello there'); }; };
Den største fordelen er at ved å se raskt på komponenten, vet vi alltid hva den skal gjøre. For eksempel kan komponent gjengi et antall komponenter. Vi kan ikke gjengi komponentene våre andre steder enn inne i render
funksjon, så det er aldri bekymring for at vi ikke vet hvor den gjengitte komponenten vår kom fra.
For å bygge innholdet til en komponent, gir React egenskaper eller rekvisitter for korte. I likhet med XML-attributter sender vi rekvisittene direkte til en komponent og kan deretter bruke rekvisittene inne i den konstruerte komponenten.
var Hello = function(props) { this.render = function() { return Hello {props.name} ; }; }; var Greeter = function() { this.render = function() { return } };
Dette fører til at komponentene våre er i en trelignende struktur, og vi har bare lov til å formidle data når vi konstruerer underordnede elementer.
I tillegg til rekvisitter, kan komponenter også ha en intern tilstand. Det mest fremtredende eksemplet på denne oppførselen vil være en klikketeller som oppdaterer verdien når en knapp trykkes. Antall klikk i seg selv vil bli lagret i staten.
Hver av forandrings- og tilstandsendringene utløser en fullstendig gjengivelse av komponenten.
Nå når alt blir gjengitt når rekvisittene eller tilstanden endres, hvorfor kommer React i seg selv så bra? Den magiske ingrediensen er 'Virtual DOM.' Hver gang noe er nødvendig for å gjengis på nytt, genereres en virtuell representasjon av den oppdaterte DOM. Virtual DOM består av lysrepresentasjoner av elementer modellert etter komponenttreet, noe som gjør prosessen med å generere dem mye mer effektiv enn å generere ekte DOM-elementer. Før du bruker endringene på den virkelige DOM, blir det utført kontroller for å avgjøre hvor nøyaktig i komponenttreet endringene skjedde, en diff blir opprettet, og bare de spesifikke endringene blir brukt.
Det er visse forutsetninger som nybegynnere må sette opp for å utvikle seg for React Native. Siden iOS var den første støttede plattformen, og den vi dekker i denne opplæringen, trenger vi macOS og Xcode, i det minste versjon 6.3. Node.js er også nødvendig. Det som hjelper er å installere Vekter gjennom Brew-pakkeforvalteren med brew install watchman
. Selv om dette ikke nødvendigvis er nødvendig, hjelper det når du arbeider med mange filer i vårt React Native-prosjekt.
For å installere React Native, trenger vi bare installer React Native kommandolinjeprogrammet med npm install -g react-native-cli
. Ringer til react-native
kommandoen hjelper oss da med å lage et nytt React Native-program. Løping react-native init HelloWorld
oppretter en mappe som heter HelloWorld
hvor kjeleplatekoden finnes.
Med React som nøkkelfunksjon og kjerneprinsippene som kommer fra React-biblioteket, la oss ta en titt på hva vi trenger for å transformere en minimal React “Hello World” -applikasjon til en React Native.
Vi bruker noen ES2015-funksjoner i dette kodeeksemplet, spesielt klasser. Det er helt mulig å holde seg til React.createClass
eller bruk et funksjonsskjema som ligner på det populære modulmønsteret.
var React = require('react'); class HelloThere extends React.Component { clickMe() { alert('Hi!'); } render() { return ( Hello {this.props.name}. Please click me. ); } } React.render(, document.getElementById('content'));
I det første trinnet må vi endre at det kreves at React-modulen bruker react-native
i stedet.
var React = require('react-native'); class HelloThere extends React.Component { clickMe() { alert('Hi!'); } render() { return ( Hello {this.props.name}. Please click me. ); } } React.render(, document.getElementById('content'));
Det som vanligvis er en del av verktøyrørledningen når du utvikler en React-webapplikasjon, er en integrert del av React Native.
Ikke overraskende er det ingen DOM på mobil. Der vi tidligere brukte, må vi bruke og der vi brukte , er komponenten vi trenger her.
import React from ‘react'; import {View, Text, Alert} from ‘react-native'; class HelloThere extends React.Component { clickMe() { Alert.alert(‘hi!'); } render() { return ( Hello {this.props.name}. Please click me. ); } } React.render(, document.getElementById('content'));
Selv om det er ganske praktisk å sette tekst direkte i elementene, kan ikke tekst i den opprinnelige verden settes direkte i en. For det må vi sette inn en komponent.
import React from ‘react'; import {View, Text, Alert} from ‘react-native'; class HelloThere extends React.Component { clickMe() { Alert.alert(‘hi!'); } render() { return ( Hello {this.props.name}. Please click me. ); } } React.render(, document.getElementById('content'));
React Native lar oss bruke Flexbox-modellering i stedet for å rote med float
og inline-block
som vi er så kjent med i nettverdenen. Det interessante er at React Native ikke bruker CSS.
import React from ‘react'; import {View, Text, StyleSheet, Alert} from ‘react-native'; class HelloThere extends React.Component { clickMe() { Alert.alert(‘hi!'); } render() { return ( Hello {this.props.name}. Please click me. ); } } var styles = StyleSheet.create({ box: { borderColor: 'red', backgroundColor: '#fff', borderWidth: 1, padding: 10, width: 100, height: 100 } }); React.render(, document.getElementById('content'));
Bruk av innebygde stiler virker forvirrende for nybegynnere. Det ligner på overgangen React-utviklere måtte gjennom når de ble konfrontert med JSX og tidligere brukte malmotorer som Handlebars eller Jade.
Tanken er at vi ikke har stilark globalt slik vi bruker CSS. Vi erklærer stilarkene direkte på komponentnivå, og så har vi all informasjonen vi trenger for å se hva komponenten vår gjør, utformingen den lager og stilene den bruker.
import React from ‘react'; import {Text} from ‘react-native'; var Headline = function(props) { this.render = () => {props.caption}; }; var headlineStyles = StyleSheet.create({ text: { fontSize: 32, fontWeight: 'bold' } }); module.exports = Headline;
Tilsvarende å klikke på websider er å trykke på et element på mobilenheten. La oss endre koden vår slik at 'varselet' dukker opp når vi trykker på elementet.
import React from ‘react'; import {View, Text, StyleSheet, TouchableOpacity, Alert} from ‘react-native'; class HelloThere extends React.Component { clickMe() { Alert.alert('Hi!') } render() { return ( Hello {this.props.name}. Please click me. ); } } var styles = StyleSheet.create({ box: { borderColor: 'red', backgroundColor: '#fff', borderWidth: 1, padding: 10, width: 100, height: 100 } }); React.render(, document.getElementById('content'));
I stedet for at hendelser er direkte tilgjengelige på komponenter, må vi eksplisitt bruke elementer som utløser hendelser, i vårt tilfelle en berøringshendelse når vi trykker på visningen. Det er forskjellige typer berørbare komponenter tilgjengelig, hver av dem gir en annen visuell tilbakemelding.
Det er mulig å oppdage hvilken plattform React Native-applikasjonen kjører på, ved å få tilgang til verdien av Platform.OS
. La oss si at vi i eksemplet ovenfor ønsket å vise en annen varselmelding basert på plattformen vi kjører på. Vi kan gjøre det slik:
... clickMe() { var message = ‘'; if(Platform.OS == ‘ios') { message = ‘Welcome to iOS!'; } else if(Platform.OS == ‘android') { message = ‘Welcome to Android!'; } Alert.alert(message); } ...
Alternativt kan select
metoden er også tilgjengelig, som gir en bryterlignende syntaks:
… clickMe() { Alert.alert(Platform.select({ ios: ‘Welcome to iOS!', android: ‘Welcome to Android!' }) ); } ...
react-native link
For å legge til en tilpasset skrift, må vi hoppe gjennom noen ringer. Først og fremst må du sørge for at fontens fulle navn og fontens filnavn er de samme: iOS vil bruke fontens fulle navn for å plukke opp fonten, mens Android bruker filnavnet.
Så hvis fontens fulle navn er myCustomFont
, må du sørge for at fontens filnavn er myCustomFont.ttf
.
Etter det må vi opprette en eiendomsmappe og peke npm til den. Vi kan gjøre det ved å opprette mappen først, under assets/fonts
i programmets rotkatalog. Enhver annen katalog vil gjøre, men dette er det konvensjonelle navnet som brukes til skrifttypekatalogen.
Vi kan fortelle npm hvor vi har eiendelene våre ved å legge til en Assets
eiendom under React's npm-integrasjon, rnpm:
'rnpm': { 'Assets': [ './assets/fonts/' ] }
Etter at vi har gjort alt det, kan vi endelig løpe react-native link
. Det vil kopiere skriftene til de riktige katalogene, og vil legge til nødvendig xml i info.plist på iOS.
Når du er ferdig, kan vi bruke fonten vår ved å bare henvise til den i et hvilket som helst stilark med fullt navn. La oss bruke den på Text
element:
import React from ‘react'; import {View, Text, StyleSheet, TouchableOpacity, Alert} from ‘react-native'; class HelloThere extends React.Component { clickMe() { Alert.alert('Hi!') } render() { return ( Hello {this.props.name}. Please click me. ); } } var styles = StyleSheet.create({ box: { borderColor: 'red', backgroundColor: '#fff', borderWidth: 1, padding: 10, width: 100, height: 100 }, message: { fontFamily: 'myCustomFont' } }); React.render(, document.getElementById('content'));
React Native bruker de samme reglene som Flexbox for å legge ut komponenter. Si at vi ønsket å plassere knappen vår nederst på skjermen: la oss pakke inn TouchableOpacity
med container View
:
Hello {this.props.name}. Please click me.
Og la oss nå definere container
stil, sammen med de andre allerede definerte stilene:
container: { flex: 1, justifyContent: 'center', alignItems: 'center' }
La oss fokusere på justifyContent
og alignItems
. Disse to egenskapene styrer hvordan komponenten er justert henholdsvis langs sin primære akse og dens sekundære akse. Som standard er primæraksen den vertikale, og sekundæraksen er den horisontale aksen (du kan endre det ved å sette egenskapen flexDirection
til row
).
justifyContent
har seks mulige verdier, den kan settes til:
flex-start
vil plassere alle elementene sammen, i begynnelsen av komponentens avgrensningsboks.flex-end
vil plassere alle elementene på slutten.center
vil plassere alle elementene i midten av avgrensningsboksen.space-around
vil spre komponentene jevnt, og vil sentrere komponentene i de opprettet avgrensningsbokser.space-evenly
vil også spre komponentene jevnt, men det vil prøve å gi like mye plass mellom komponentene og de andre grensene.space-between
vil spre komponentene ved å holde avstanden mellom tilstøtende komponenter likt.alignItems
kan settes til fire mulige verdier: flex-start
, flex-end
, center
, og stretch
. De tre første oppfører seg som de gjør for justifyContent
, mens stretch
vil sette komponenten til å oppta all tilgjengelig plass langs aksen, slik at aksen blir fullstendig fylt.
Så siden vi vil ha TouchableOpacity
for å vises nederst og sentrert langs den horisontale aksen, kan vi endre stilen slik:
container: { flex: 1, justifyContent: 'flex-end', alignItems: 'center' }
Mer informasjon om verdiene justifyContent
og alignItems
kan ha kan bli funnet her og her .
Når vi utvikler oss med React for nettleseren, trenger vi bare å definere et monteringspunkt, ring React.render
, og la React gjøre sin magi. I React Native er dette litt annerledes.
import React from ‘react'; import {View, Text, StyleSheet, TouchableOpacity, Alert, Platform} from ‘react-native'; class HelloThere extends React.Component { clickMe() { Alert.alert(Platform.select({ ios: ‘Welcome to iOS!', android: ‘Welcome to Android!' })); } render() { return ( Hello {this.props.name}. Please click me. ); } } var styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'flex-start', alignItems: 'center' }, box: { borderColor: 'red', backgroundColor: '#fff', borderWidth: 1, padding: 10, width: 100, height: 100 }, message: { fontFamily: 'myCustomFont' } }); var MainComponent = function() { this.render = function() { return ; } }; AppRegistry.registerComponent('MainComponent', function() { return MainComponent; });
Vi må registrere komponenten for Objective-C-siden av ting, som gjøres ved hjelp av AppRegistry
gjenstand. Navnet vi gir må samsvare med navnet i Xcode-prosjektet.
Vår Hello World React Native-applikasjon har betydelig flere kodelinjer enn sin motpart på nettet, men på den annen side tar React Native separasjon av bekymringer litt lenger, spesielt fordi stiler er definert med komponenten.
Som en sidemerknad, bør vi ikke gjenopprette clickMe
metoden til this
kontekst i render
metode, spesielt hvis vår React (Native) -applikasjon blir litt mer kompleks. Den gjenoppretter metoden på hvert gjengivelsesanrop som kan bli ganske mye. Alternativet er å binde metoden inne i konstruktøren.
For å kjøre applikasjonen, må vi erstatte innholdet i index.ios.js
fil med kodebiten til den transformerte applikasjonen vår fra siste trinn. Da trenger vi bare å åpne Xcode-prosjektet og trykke på den store Run-knappen. Først åpnes en terminal med React Native-serveren, og deretter vises simulatorvinduet. React Native-serveren oppretter en pakke som den opprinnelige applikasjonen deretter henter. Dette gir mulighet for en nettutviklingslignende hurtigutviklingssyklus, der endringer vil reflekteres nesten umiddelbart i simulatoren.
For Android er det nok å legge til følgende i package.json
fil, under scripts
:
'android-linux': 'react-native bundle --platform android --dev false --entry-file index.ios.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/ main/res && react-native run-android'
Og så løp npm run android-linux
. Forsikre deg om at android/app/src/main/assets
katalogen eksisterer på forhånd.
Etter at terminalen har dukket opp, vil applikasjonen vår vises i simulatoren. Ved å trykke på CMD + D vises en utviklingsmeny. Ved å klikke på ruten vises et varsel. IOS-versjonen:
Og Android gjengir noe slikt:
For distribusjon ville det ikke fungere å ha et program som peker til en lokal utviklingsserver. Av denne grunn kan vi lage pakken for bruk når React Native-serveren ikke kjører med kommandoen react-native bundle
. I så fall må vi oppdatere didFinishLaunchingWithOptions
metoden for AppDelegate
for å bruke den frakoblede pakken.
Dette eksempelet applikasjonen er også tilgjengelig på Github .
En annen ting som er verdt å nevne er at vi ikke bare bruker React-konsepter og JavaScript til mobilapplikasjonene våre, men noen av arbeidsflytene som nettutviklere er vant til, er også tilgjengelige med React Native. Når vi kommer fra webutvikling, er vi vant til utviklerverktøy, inspeksjon av elementer og live-omlasting.
Måten React Native fungerer på er at den legger alle JavaScript-filene våre i en pakke. Denne pakken blir enten servert fra en server eller samlet sammen med applikasjonen. Den første er utrolig nyttig for utvikling i Simulatoren, da vi kan aktivere live-omlasting. Utviklermenyen React gir er på ingen måte så mektig som Chrome Developer Tools, men den gir en veldig nettlignende utvikleropplevelse med live omlasting og feilsøking med Chrome (eller Safari) utvikler / feilsøkingsverktøy.
Nettutviklere er kjent med JSFiddle eller JSBin, en online lekeplass for raske nettester. Det er et lignende miljø som lar oss prøve React Native i en nettleser.
Jeg hadde opprinnelig foreslått en mer forsiktig tilnærming til React Native. I dag er det et modent og solid valg.
En av de store fordelene med React er at den ikke pålegger arbeidsflyten din, siden den bare representerer visningslaget. Vil du definere din egen Grunt-rørledning? Eller vil du heller bruke Webpack? Og vil du bruke Backbone.js for modellbehovene dine? Eller vil du gå med vanlige JavaScript-objekter? Svarene på alle disse spørsmålene er helt opp til deg, fordi React ikke setter noen begrensning på disse valgene. Som det offisielle nettstedet hadde sagt det: 'Siden React ikke legger til grunn antagelser om resten av teknologibakken din, er det enkelt å prøve det på en liten funksjon i et eksisterende prosjekt.'
Til en viss grad gjelder dette også for React Native. Mobilutviklere kan integrere React Native som en del av applikasjonen, dra nytte av den webinspirerte arbeidsflyten for utvikling og velge å integrere biblioteket i større skala hvis det er behov.
I alle fall er en ting sikker: React Native forsvinner ikke . Facebook har en enorm andel i at den har flere React Native-drevne applikasjoner i appbutikker. Samfunnet rundt React Native er stort og fortsetter å vokse.
I slekt: Bygg en QR-skanner: A React Native Camera TutorialReact Native er et rammeverk for å bygge native iOS- og Android-applikasjoner ved hjelp av JavaScript. Den er basert på de samme konseptene som React, men bruker innfødte komponenter i stedet for webkomponenter for å gjengi et brukergrensesnitt (UI).
React er et front-end JavaScript-bibliotek, designet rundt konseptet med å bruke deklarative visninger for effektivitet og forutsigbarhet.
Hvis du støtter mer enn én plattform, gir React Native en solid fordel når det gjelder gjenbruk av kjernekode fra appen din. Du må fremdeles oppgi noen plattformspesifikk kode, men det vil sikkert være mindre å skrive og vedlikeholde enn om du skrev en innfødt app for hver plattform.
En innfødt app er en som er samlet for og kjører direkte på målplattformen. Som standard vil den ha et 'utseende' som passer inn i plattformen. React Native har som mål å gi deg samme innfødte utseende og følelse mens du fremdeles gir ekstra bærbarhet og en kjent metodikk.