Du bist aufgewacht. Die Sonne scheint, die Vögel zwitschern. In der Welt befindet sich niemand im Krieg mit irgendjemandem, niemand hungert und der gleiche Code kann in Webprojekten und in nativen Anwendungen verwendet werden. Wie schön wäre es! Leider ist am Horizont nur universeller Code zu sehen, aber der Weg dorthin ist auch heute noch voller Überraschungen.

Das Material, dessen Übersetzung wir heute veröffentlichen, ist eine kleine, aber recht detaillierte Anleitung zur Entwicklung universeller Anwendungen mit React Native.
Warum ist das alles?
Die Abkürzung "PWA" (
Progressive Web Apps , Progressive Web Applications) ist heute allen bekannt. Dieses aus drei Buchstaben bestehende Akronym scheint nur ein Wal in einem Meer technischer Begriffe zu sein. Diese beliebte Technologie ist jedoch immer noch nicht ohne
Mängel . Mit solchen Anwendungen sind viele technologische Schwierigkeiten verbunden. Es gibt Situationen, in denen ein Entwickler gezwungen ist, gleichzeitig native Anwendungen und Webanwendungen zu erstellen.
Hier ist ein guter Artikel zum Vergleich von PWA und nativen Anwendungen.
Vielleicht sollte sich das Geschäft nur auf native Anwendungen konzentrieren? Nein, das ist es nicht wert. Das ist ein großer Fehler. Infolgedessen wird die Entwicklung einer einzigen universellen Anwendung zu einem logischen Schritt. Auf diese Weise können Sie die Entwicklungszeit verkürzen und die Kosten für die Erstellung und Unterstützung von Projekten senken. Es sind diese Eigenschaften universeller Anwendungen, die mich zu einem kleinen Experiment veranlasst haben.
Dies ist ein universelles Anwendungsbeispiel aus dem Bereich des elektronischen Handels für die Bestellung von Lebensmitteln. Nach dem Experiment habe ich eine Vorlage für zukünftige Projekte und für die weitere Forschung erstellt.
Papu ist eine Anwendung zum Bestellen von Lebensmitteln für Android, iOS und das InternetAnwendungsbausteine
Hier verwenden wir React, daher müssen wir die Anwendungslogik von der Benutzeroberfläche trennen. Es ist am besten, ein System zu verwenden, um den Status einer Anwendung wie Redux oder Mobx zu steuern. Ein solcher Schritt macht die Logik der Anwendung sofort universell. Es kann ohne Änderungen auf verschiedenen Plattformen verwendet werden.
Der visuelle Teil der Anwendung ist eine weitere Konversation. Um die Anwendungsschnittstelle zu erstellen, benötigen Sie einen universellen Satz von Grundelementen, Grundbausteinen. Sie sollten sowohl im Web als auch in der nativen Umgebung funktionieren. Leider sind die Sprache des Webs und die Sprache der nativen Plattformen zwei verschiedene Dinge.
Ein Standard-Webcontainer wird Sie beispielsweise folgendermaßen kontaktieren:
<div> ! - !</div>
Und einheimisch - so:
<View>! - React Native</View>
Einige kluge Leute haben einen Ausweg aus dieser Situation gefunden. Die Ausgabe waren spezialisierte Elementbibliotheken. Einer meiner Favoriten ist die wunderbare
React Native Web Library. Es kümmert sich nicht nur um die Grundelemente der Anwendung und ermöglicht die Verwendung von React Native-Komponenten im Web (nicht alle Komponenten!), Sondern bietet auch Zugriff auf verschiedene React Native-APIs. Unter ihnen sind
Geolocation
,
Platform
,
Animated
,
AsyncStorage
und viele andere. Schauen Sie sich die großartigen Beispiele an, die im
Handbuch für diese Bibliothek zu finden sind.
Muster
Wir haben die Primitiven herausgefunden. Wir müssen jedoch noch die Umgebung für die Webentwicklung und die native Entwicklung verbinden. Mein Projekt verwendet
die Create- React
-App (für eine Webanwendung) und
ein Initialisierungsskript von React Native (für eine native Anwendung ohne Expo). Zuerst habe ich ein Projekt mit diesem Befehl erstellt:
create-react-app rnw_web
. Dann erstellte er ein zweites Projekt:
react-native init raw_native
. Dann habe ich nach dem Beispiel von Victor Frankenstein die
package.json
Dateien aus diesen beiden Projekten genommen und zusammengeführt. Danach habe ich im Ordner des neuen Projekts die neue
yarn
eingezogen. Hier ist die betreffende
package
:
{ "name": "rnw_boilerplate", "version": "0.1.0", "private": true, "dependencies": { "react": "^16.5.1", "react-art": "^16.5.1", "react-dom": "^16.5.1", "react-native": "0.56.0", "react-native-web": "^0.9.0", "react-navigation": "^2.17.0", "react-router-dom": "^4.3.1", "react-router-modal": "^1.4.2" }, "devDependencies": { "babel-jest": "^23.4.0", "babel-preset-react-native": "^5", "jest": "^23.4.1", "react-scripts": "1.1.5", "react-test-renderer": "^16.3.1" }, "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "test": "jest", "start-ios": "react-native run-ios", "start-web": "react-scripts start", "build": "react-scripts build", "test-web": "react-scripts test --env=jsdom", "eject-web": "react-scripts eject" } }
Bitte beachten Sie, dass diese Version der Datei keine Navigationsfunktionen enthält. Als Nächstes müssen Sie alle Quellcodedateien aus den Ordnern der Webanwendung und der nativen Anwendung in den Ordner des neuen einheitlichen Projekts kopieren.
Ordner, die in ein neues Projekt kopiert werden sollenErstellen Sie nun im Ordner
src
, der sich im Verzeichnis des neuen Projekts befindet, zwei Dateien:
App.js
und
App.native.js
. Dank
Webpack können wir Dateinamenerweiterungen verwenden, um dem
Bundler mitzuteilen, wo welche Dateien verwendet werden sollen. Das Trennen von
App
Dateien ist von entscheidender Bedeutung, da wir für die Navigation in Apps unterschiedliche Ansätze verwenden werden.
Hier ist die
App.js
Datei für das Web.
react-router
zur Navigation verwendet.
// App.js - WEB import React, { Component } from "react"; import { View } from "react-native"; import WebRoutesGenerator from "./NativeWebRouteWrapper/index"; import { ModalContainer } from "react-router-modal"; import HomeScreen from "./HomeScreen"; import TopNav from "./TopNav"; import SecondScreen from "./SecondScreen"; import UserScreen from "./UserScreen"; import DasModalScreen from "./DasModalScreen"; const routeMap = { Home: { component: HomeScreen, path: "/", exact: true }, Second: { component: SecondScreen, path: "/second" }, User: { component: UserScreen, path: "/user/:name?", exact: true }, DasModal: { component: DasModalScreen, path: "*/dasmodal", modal: true } }; class App extends Component { render() { return ( <View> <TopNav /> {WebRoutesGenerator({ routeMap })} <ModalContainer /> </View> ); } } export default App;
Hier ist die
App.js
für die React Native App. Hier wird die
react-navigation
.
// App.js - React Native import React, { Component } from "react"; import { createStackNavigator, createBottomTabNavigator } from "react-navigation"; import HomeScreen from "./HomeScreen"; import DasModalScreen from "./DasModalScreen"; import SecondScreen from "./SecondScreen"; import UserScreen from "./UserScreen"; const HomeStack = createStackNavigator({ Home: { screen: HomeScreen, navigationOptions: { title: "Home" } } }); const SecondStack = createStackNavigator({ Second: { screen: SecondScreen, navigationOptions: { title: "Second" } }, User: { screen: UserScreen, navigationOptions: { title: "User" } } }); const TabNav = createBottomTabNavigator({ Home: HomeStack, SecondStack: SecondStack }); const RootStack = createStackNavigator( { Main: TabNav, DasModal: DasModalScreen }, { mode: "modal", headerMode: "none" } ); class App extends Component { render() { return <RootStack />; } } export default App;
So habe ich eine einfache Anwendungsvorlage erstellt und die Plattform für die weitere Arbeit vorbereitet. Sie können diese Vorlage ausprobieren, indem Sie sich
dieses Repository ansehen.
Jetzt werden wir diese Vorlage etwas komplizieren und ein Routing- / Navigationssystem hinzufügen.
Navigationsprobleme und ihre Lösungen
Eine Anwendung benötigt, sofern sie nicht aus einem einzigen Bildschirm besteht, eine Art Navigationssystem. Jetzt (wir sprechen über September 2018) gibt es nur ein solches universelles Arbeitssystem, das sowohl für das Web als auch für native Anwendungen geeignet ist. Es geht um den
React Router . Für das Web funktioniert diese Lösung gut, aber bei React Native-Projekten ist nicht alles so klar.
In React Router Native gibt es keine Übergänge zwischen Bildschirmen, es gibt keine Unterstützung für die Schaltfläche Zurück (für die Android-Plattform), es gibt keine modalen Bildschirme, Navigationsleisten und andere Funktionen. Andere Navigationswerkzeuge wie
React Navigation verfügen über diese Funktionen.
Ich habe diese spezielle Bibliothek benutzt, aber Sie können etwas anderes aufgreifen. Daher ist in meinem Projekt React Router für die Navigation in der Webanwendung und React Navigation für die Navigation in der nativen Anwendung verantwortlich. Dies schafft jedoch ein neues Problem. Tatsache ist, dass die Ansätze zur Navigation und zur Übertragung von Parametern in diesen Systemen sehr unterschiedlich sind.
Um den Geist von React Native Web zu bewahren und überall einen ähnlichen Ansatz wie in nativen Anwendungen zu verwenden, habe ich mich der Lösung dieses Problems zugewandt, indem ich Webrouten erstellt und in HOC verpackt habe. Dies gab mir die Möglichkeit, eine API zu erstellen, die an React Navigation erinnert.
Dieser Ansatz ermöglichte es mir, zwischen den Bildschirmen einer Webanwendung zu wechseln, sodass keine separaten Komponenten für zwei Arten von Anwendungen erstellt werden mussten.
Der erste Schritt bei der Implementierung dieses Mechanismus besteht darin, ein Objekt mit einer Beschreibung der Routen für die Webanwendung zu erstellen:
import WebRoutesGenerator from "./NativeWebRouteWrapper"; // , React Router HOC const routeMap = { Home: { screen: HomeScreen, path: '/', exact: true }, Menu: { screen: MenuScreen, path: '/menu/sectionIndex?' } } // render <View> {WebRoutesGenerator({ routeMap })} </View>
In der Tat ist hier eine Kopie der React Navigation-Erstellungsfunktion mit zusätzlichen React Router-spezifischen Funktionen.
Als Nächstes erstelle ich mit meiner Hilfsfunktion
react-router
Routen und verpacke sie in HOC. Auf diese Weise können Sie die
screen
klonen und ihren Eigenschaften eine
navigation
hinzufügen. Dieser Ansatz ahmt das Verhalten von React Navigation nach und stellt Methoden wie
goBack()
,
getParam()
,
getParam()
.
Modale Bildschirme
React Navigation ermöglicht dank
createStackNavigator
, dass eine bestimmte Seite der Anwendung in Form eines modalen Bildschirms von unten angezeigt wird. Um dies in einer Webanwendung zu erreichen, musste ich die
React Router Modal- Bibliothek verwenden. Um mit dem modalen Bildschirm zu arbeiten, müssen Sie dem
routeMap
Objekt zunächst die entsprechende Option
routeMap
:
const routeMap = { Modal: { screen: ModalScreen, path: '*/modal', modal: true
Außerdem muss die
<ModalContainer />
-Komponente aus der
<ModalContainer />
react-router-modal
Bibliothek zum Anwendungslayout hinzugefügt werden. Dort wird die entsprechende Seite angezeigt.
Navigation zwischen Bildschirmen
Dank des HOC unserer Entwicklung (vorübergehend heißt diese Komponente
NativeWebRouteWrapper
, und dies ist übrigens ein schrecklicher Name) können wir fast dieselben Funktionen wie in React Navigation verwenden, um die Bewegung zwischen Seiten in der Webversion der Anwendung zu organisieren:
const { product, navigation } = this.props <Button onPress={navigation.navigate('ProductScreen', {id: product.id})} title={`Go to ${product.name}`} /> <Button onPress={navigation.goBack} title="Go Back" />
Kehren Sie zum vorherigen Bildschirm zurück.
In React Navigation können Sie zu
n
Bildschirmen zurückkehren, die sich im Navigationsstapel befinden. Ähnlich ist in React Router nicht verfügbar, es gibt keinen Navigationsstapel. Um dieses Problem zu lösen, müssen wir die
pop
Funktion unseres eigenen Designs in den Code importieren. Wenn wir sie anrufen, geben wir ihr verschiedene Parameter:
import pop from '/NativeWebRouteWrapper/pop' render() { const { navigation } = this.props return ( <Button onPress={pop({screen: 'FirstScreen', n: 2, navigation})} title="Go back two screens" /> ) }
Wir beschreiben diese Parameter:
screen
- Der Name des Bildschirms (wird von React Router in der Webversion der Anwendung verwendet).n
ist die Anzahl der Bildschirme, die mithilfe des Stapels (mithilfe von React Navigation) zurückgegeben werden sollen.navigation
- ein Objekt, das Navigation bietet.
Arbeitsergebnisse
Wenn Sie mit der hier vorgestellten Idee der Entwicklung universeller Anwendungen experimentieren möchten, habe ich zwei Vorlagen erstellt.
Die erste ist eine saubere, universelle Umgebung für die Entwicklung von Webanwendungen und nativen Anwendungen.
Die zweite ist im Wesentlichen die erste Vorlage, die aufgrund meines Systems zur Organisation der Navigation in der Anwendung erweitert wurde.
Hier ist eine Papu-Demo-Anwendung, die auf den obigen Überlegungen basiert. Es ist voller Fehler und Sackgassen, aber Sie können es selbst zusammenstellen, in einem Browser und auf einem mobilen Gerät ausführen und sich in der Praxis ein Bild davon machen, wie alles funktioniert.
Zusammenfassung
Die React-Entwickler-Community benötigt natürlich eine universelle Bibliothek für die Organisation der Anwendungsnavigation, da dies die Entwicklung von Projekten wie dem, über das wir gesprochen haben, vereinfacht. Es wäre sehr schön, wenn die React Navigation-Bibliothek im Web funktionieren würde (tatsächlich ist diese Funktion bereits
verfügbar , aber die Arbeit damit ist nicht ohne Schwierigkeiten).
Liebe Leser! Nutzen Sie React, um universelle Anwendungen zu erstellen?
