Flutter, React Native und NativeScript: Kopf an Kopf im Cross-Plattform-Rennen
Seite 2: Eigene Designphilosophie
HTML- oder XML-Attribute nehmen in NativeScript zusätzlich bis zu einem gewissen Grad Code auf. Dabei handelt es sich um eine Best Practice, deren Kenntnisnahme zum Verständnis der der Designphilosophie von React beziehungsweise React Native unbedingt erforderlich ist.
Facebook hat sich beim Entwickeln von React dazu entschlossen, die Beziehung zwischen Code und Markup umzudrehen. Während üblicherweise HTML- bzw XML-Dateien Code aufnehmen, nimmt bei React Sourcecode eine als JSX bezeichnete Beschreibungssprache auf. Ihr Format ist an XML angelehnt und legt unter anderem das Aussehen von Steuerelementen fest. Ein Beispiel ist folgender Codeausschnitt:
export default class App
extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
Change code in the editor and watch
it change on your phone! Save to get
a shareable url.
</Text>
<Card>
<AssetExample />
</Card>
</View>
);
}
Neben der gewöhnungsbedürftigen Syntax ist vor allem das Vorhandensein der render
-Methode relevant. Das Betriebssystem beziehungsweise der Interpreter ruft sie auf, und sie liefert einen JSX-String zurück. Letzteren passt React Native an das Aussehen der Hostplattform an.
Bemerkenswert ist der Ansatz zum Parametrieren von Steuerelementen zur Laufzeit. Statt wie in NativeScript direkt in die Attribute zu schreiben, treffen Entwickler bei React Native auf zwei Arten von Attributen. In geschwungenen Klammern gefasste Begriffe sind sogenannte Props. Der Konstruktor des jeweiligen Objekts legt sie fest, worauf sie für den Rest ihres Daseins konstant bleiben.
Veränderliche Eigenschaften
Eigenschaften, die zur Laufzeit permanenten Veränderungen unterliegen, befinden sich stattdessen in einem Speicher, der an einen Zustandsautomat erinnert. Zur Demonstration des Statussystems soll ein von Facebook bereitgestelltes Beispiel dienen, das ein Widget zum Blinken bringt. Die erste Aktion der von Component
abgeleiteten Klasse ist, einen Intervall-Handler anzulegen:
class Blink extends Component {
componentDidMount(){
// Toggle the state every second
setInterval(() => (
this.setState(previousState => (
{ isShowingText: !previousState.isShowingText }
))
), 1000);
}
//state object
state = { isShowingText: true };
Auffällig ist, dass Blink
die Methode setInterval
benutzt, um auf das Zustandsobjekt des Steuerelements zuzugreifen. Direkte Zugriffe auf den im Steuerelement gehaltenen Zustand gelten in React und React Native als Antipattern.
Das Erstellen des Widgets erfolgt auf gewohnte Weise folgendermaßen:
render() {
if (!this.state.isShowingText) {
return null;
}
return (
<Text>{this.props.text}</Text>
);
}
}
Flutter setzt auf ein ähnliches Verfahren, ist in diesem Bereich aber noch radikaler. Der Lebenszyklus der Steuerelemente ist kürzer als in React, und die Unterteilung zwischen zustandshaltenden und zustandslosen Widgets ist ebenfalls strenger.
In beiden Fällen gilt, dass Entwickler, die Embarcadero, Qt oder Visual Basic gewohnt sind, umdenken müssen. Der Autor benötigte einige Stunden, um sich an die Eigenarten von Flutter zu gewöhnen.
In der Anfangszeit von React Native enthielten die Projektgerüste zwei Dateigruppen, um Views für Android und iOS zu generieren. Mittlerweile ist das nicht mehr der Fall, aber nach wie vor funktionieren zahlreiche Steuerelementen nur auf einer der beiden Plattformen. Unter NativeScript ist die Anzahl der plattformspezifischen Widgets offensichtlich um einiges geringer.