JSX-Einführung

HTML, das JavaScript kann

05.01.2024
Von 
Matthew Tyson ist Java-Entwickler und schreibt unter anderem für unsere US-Schwesterpublikation Infoworld.com.
JSX hat großen Einfluss auf das Frontend-Engineering. Eine Einführung in die HTML-basierte JavaScript-Templating-Sprache.
Wenn Sie JSX einmal verstanden haben, können Sie dieses Knowhow auf andere Reactive-Frameworks und ihre Templating-Sprachen übertragen.
Wenn Sie JSX einmal verstanden haben, können Sie dieses Knowhow auf andere Reactive-Frameworks und ihre Templating-Sprachen übertragen.
Foto: Kishore Newton | shutterstock.com

JSX bietet die Möglichkeit, HTML-Code innerhalb von JavaScript zu schreiben. Dabei fühlt es sich allerdings eher danach an, als würde man JavaScript innerhalb von HTML nutzen. Als Templating-Sprache wird sie von einigen Entwicklern geliebt und von anderen verabscheut. In diesem Artikel lesen Sie, wie JSX funktioniert - und warum es von Bedeutung ist.

Templates erstellen mit JSX

Eingeführt wurde JSX (JavaScript Syntax Extension) als Templating-Sprache für das populäre React-Framework. Sie ermöglicht, die Struktur einer Anwendungsansicht mit HTML-Markup zu definieren, das mit dem JavaScript-Kontext der Anwendung interagiert. Inzwischen ist JSX der Defacto-Standard für reaktive Templating-Engines - und hat zahlreiche andere inspiriert (Vue, Svelte, Angular). Der eben beschriebene Grundgedanke von JSX bricht mit der Konvention, Ansicht (View) und Verhalten (Behavior) voneinander zu trennen. Das ist auch ursächlich für die gespaltene Entwickler-Community, wenn es um JSX geht.

Unabhängig von dieser prinzipiellen Kontroverse fokussieren wir uns in diesem Artikel darauf, zu verstehen, wie JSX zu verwenden ist. Im Folgenden sehen Sie, wie JSX in einer React-Anwendung aussieht (zur Live-Version):

import React from 'react';

export function App(props) {

return (

<div className='App'>

<h1>Greetings from InfoWorld</h1>

<h2>This is some JSX</h2>

</div>

);

}

Wenn Sie die Inhalte innerhalb von <div> betrachten, werden Sie feststellen, dass es sich nur um HTML-Code handelt - der in JavaScript verpackt ist. Das HTML stellt einen Rückgabewert (Return Value) für die Funktion App (eine funktionale Komponente in React). Das JSX-Markup ist der Rückgabewert der Funktion.

Im Wesentlichen teilt der JSX-Rückgabewert der React-Rendering-Engine mit, wie der Output der Komponente aussieht.

HTML in JavaScript

Inzwischen ist es alltäglich geworden, Markup als JavaScript-Einbettung zu sehen. In der Tat ist es auch sehr praktisch, beides zusammen zu bringen. Nehmen wir an, wir wollen eine Variable in das Markup einfügen. Das ließe sich folgendermaßen bewerkstelligen (Live-Version):

export function App(props) {

let [name, setName] = React.useState("User");

return (

<div className='App'>

<h1>Greetings from InfoWorld</h1>

<h2>Hello {name}</h2>

</div>

);

}

Jetzt verwenden wir die Variable "name" innerhalb des JSX-Parts. Diese Variable wird mit dem React.useState-Hook erstellt. Es kann sich aber um eine beliebige JavaScript-Variable handeln, solange sie im Geltungsbereich liegt. Bei der Verwendung funktionaler Komponenten ist der useState-Hook der richtige Weg, um eine Variable in JSX zu nutzen.

Die geschweiften Klammern, die name im JSX-Template umgeben, bezeichnen eine JSX-Expression. Diese ermöglichen es Ihnen, JavaScript-Expressions innerhalb des Markups auszuführen - sowie auf Variablen Bezug zu nehmen. Letzteres funktioniert, weil das JavaScript im größeren Kontext des umgebenden Codes ausgeführt wird. Zusammengefasst erhalten Sie also alle Möglichkeiten von JavaScript, importierte Bibliotheken wie das React-Framework und eine vollständige HTML-Syntax, die auf diese Funktionen verweisen kann.

Dabei gilt es zu beachten, dass JSX zwar Expressions nutzen kann, aber kein vollständiges JavaScript. Es gibt das Ergebnis der Expression in der Ansicht an der Stelle aus, an der es im Template zu finden ist. Dinge, die keine Value zurückgeben, etwa Loops, funktionieren nicht. Insofern unterscheidet sich JSX von anderen Templating-Tools.

Looping mit JSX

Looping gehört zu den wichtigeren Dingen, die Sie mit JSX erledigen können. Nehmen wir an, wir haben ein Array von Hunderassen im Gültigkeitsbereich und wollen diese nun anzeigen lassen. Das würde folgendermaßen funktionieren (Live-Version):

<div className='App'>

<h1>Greetings from InfoWorld</h1>

<h2></h2>

<h3>{breeds.map((breed) => {

return <li key={breed}>{breed}</li>;

})}</h3>

</div>

Wir verwenden hier die map-Funktion, um die Hunderassen zu durchlaufen und das Markup für jede einzelne auszugeben. Das Ergebnis ist HTML/JSX innerhalb von JavaScript, innerhalb von HTML/JSX, innerhalb von JavaScript. Die Code-Menge ließe sich noch weiter reduzieren, indem wir das Return-Statement weglassen:

<h3>{breeds.map((breed) => <li key={breed}>{breed}</li> )}</h3></code>

Denken Sie dabei daran, dass Sie die anderen funktionalen Methoden wie filter und reduce verwenden können, um Collections als Loops auszugeben. Sie können auch immer im JavaScript der jeweiligen Komponente selbst die Datenvariablen ändern und diese dann in der JSX anzeigen, falls erforderlich. Sie können sogar den HTML-Code innerhalb des JavaScript schreiben und ihn direkt in der JSX anzeigen.

Conditionals bei JSX

Eine weitere Schlüsselfunktion bei JSX ist der Umgang mit Conditional Control Flow wie if/then/else. Wenn wir beim Looping der Hunderassen aus unserem Beispiel bestimmte Bedingungen prüfen wollen - etwa ob ein breedOrigin-Feld existent ist - funktioniert das (auf Grundlage unseres bisherigen Aufbaus) so (Live-Version):

<h3>{breeds.map((breed) =>

<li key={breed.name}>{

breed.breedInfo ? breed.name + ": " + breed.breedInfo : breed.name}</li> )}</h3>

Hierbei nutzen wir einen ternären Operator (X ? Y : Z), der üblicherweise verwendet wird, um if/then/else-Entscheidungen innerhalb einer JSX-Expression zu treffen.

Eine weitere Conditional-Rendering-Möglichkeit besteht darin, einen Test Case zu verwenden. Dabei wird das Markup nur dann gerendert, wenn der Test erfolgreich verläuft. Wollen wir die Liste beispielsweise nur rendern, wenn das Array Elemente aufweist (ein häufiges Szenario, wenn Daten von einer Remote-API geladen werden), würden wir so vorgehen (Live-Version):

<div className='App'>

<h1>Greetings from InfoWorld</h1>

<h2></h2>

{ breeds.length > 0 && <>

<h3>{breeds.map((breed) => <li key={breed.name}>{breed.breedInfo ? breed.name + ": " + breed.breedInfo : breed.name}</li> )}</h3>

</>

}

</div>

Wenn Sie die breeds-Variable als leeres Array setzen, wird das JSX nichts darstellen. Wahrscheinlich haben Sie in obenstehendem Code auch die leeren Element-Tags bemerkt (<> und </>). Dabei handelt es sich um React-Fragmente, die von JSX unterstützt werden. Wir hätten auch ein <div> verwenden können, aber <> ist idiomatischer. Mit Fragmenten können Sie viele JSX-Elemente verpacken, ohne einen nicht-semantischen Wrapper zu erstellen.

Events in JSX

Eine weitere essenzielle JSX-Fähigkeit, die Sie kennen sollten, ist die Ereignisbehandlung. Angenommen, wir möchten, dass Benutzer auf eine Hunderasse klicken können, um die Wikipedia-Seite für diese zu öffnen. Das ließe sich folgendermaßen umsetzen (Live-Version):

let [breeds, setBreeds] = React.useState([

{name:'Shih Tzu',breedInfo:'Pekanese and Lhasa Apso cross',link:'https://en.wikipedia.org/wiki/Shih_Tzu'},

{name:'Labradoodle', link:'https://en.wikipedia.org/wiki/Labradoodle'},

{name:'Vizla',breedInfo:'Hungarian breed'},

{name:'Catahoula'}

]);

const handleBreedClick = (wikiLink) => {

window.open(wikiLink, '_blank');

};

return (

<div className='App'>

<h1>Greetings from InfoWorld</h1>

<h2></h2>

{ breeds.length > 0 && <>

<h3>

{breeds.map((breed) =>

<li key={breed.name} onClick={() => handleBreedClick(breed.link)}>{breed.breedInfo ? breed.name + ": " + breed.breedInfo : breed.name}

</li>

)}

</h3>

</>

}

</div>

);

Hier definieren wir eine handleBreedClick-Funktion, um auf den Event zu reagieren. Das öffnet den Wikipedia-Link in einem neuen Fenster. Um das Ereignis zu senden, verwenden wir einen JSX onClick-Handler (onClick={() => handleBreedClick(breed.link)}). Der funktioniert genauso wie ein normaler HTML-Handler - lediglich die Schreibweise unterscheidet sich.

Darüber hinaus können Sie auch Inline-Event-Handler definieren - etwa eine klickbare Alarmmeldung: <li onClick={() => { alert(breed.name)}} />. Im Allgemeinen können Sie JSX-Expressions in geschweiften Klammern verwenden, um Werte für Properties von HTML-Elementen anzugeben.

Styling mit JSX

JSX-Elemente unterstützen auch CSS-Styles. Hier ein Beispiel (Live-Version):

const listItemStyle = {

cursor: 'pointer',

margin: '10px 0',

padding: '5px',

backgroundColor: '#f5f5f5',

border: '1px solid #ccc',

borderRadius: '5px',

};

// … same

<li style={listItemStyle} ... </li>

Genau wie bei den Ereignissen definieren wir eine Variable in JavaScript und verweisen dann in der Property auf sie. In diesem Fall verwenden wir die style-Eigenschaft und versehen sie mit einem JavaScript-Objekt. Das Objekt sollte aus einer Reihe von Key Values bestehen, wobei der Schlüssel der Name der CSS-Eigenschaft und der Wert den CSS-Value-String darstellt.

Um einen Inline-Stil zu verwenden, verwenden Sie das Format der doppelten geschwungenen Klammer (Live-Version):

<li style={{backgroundColor:'#f5f5f5',padding:'5px'}} …>

(fm)

Dieser Beitrag basiert auf einem Artikel unserer US-Schwesterpublikation Infoworld.