Aufbau wiederverwendbarer Reaktionskomponenten mit Rückenwind

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ Tailwind ist ein beliebtes Utility-First-CSS-Framework, das Webentwicklern Low-Level-Klassennamen bietet. Es hat kein JavaScript und funktioniert gut mit bestehenden Frameworks wie React, Vue, Angular, Ember und anderen. Obwohl dies positiv ist, kann es für neue Entwickler verwirrend sein, zu verstehen, wie sie Tailwind in ihre Anwendungen integrieren können. In diesem Artikel untersuchen wir Möglichkeiten zum Erstellen wiederverwendbarer React-Komponenten mit Tailwind.

In diesem Beitrag sehen wir uns verschiedene Möglichkeiten an, wie Sie wiederverwendbare React-Komponenten erstellen können, die Tailwind unter der Haube nutzen und gleichzeitig eine nette Schnittstelle zu anderen Komponenten bereitstellen. Dadurch wird Ihr Code verbessert, indem Sie von langen Listen von Klassennamen zu semantischen Requisiten wechseln, die einfacher zu lesen und zu warten sind.

Sie müssen mit React gearbeitet haben, um diesen Beitrag gut zu verstehen.

Tailwind ist ein sehr beliebtes CSS-Framework, das Hilfsklassen auf niedriger Ebene bereitstellt, um Entwicklern beim Erstellen benutzerdefinierter Designs zu helfen. Es ist in den letzten Jahren immer beliebter geworden, weil es zwei Probleme wirklich gut löst:

  1. Tailwind macht es einfach, iterative Änderungen an HTML vorzunehmen, ohne Stylesheets durchsuchen zu müssen, um passende CSS-Selektoren zu finden.
  2. Tailwind hat vernünftige Konventionen und Standardwerte. Dies erleichtert den Einstieg, ohne CSS von Grund auf neu schreiben zu müssen.

Fügen Sie die umfassende Dokumentation hinzu und es ist keine Überraschung, warum Tailwind so beliebt ist.

Diese Methoden helfen Ihnen, Code umzuwandeln, der wie folgt aussieht:

 <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Enable </button>

So sieht Code aus:

 <Button size="sm" textColor="white" bgColor="blue-500"> Enable </Button>

Der Unterschied zwischen beiden Snippets besteht darin, dass wir im ersten ein standardmäßiges HTML-Schaltflächen-Tag verwendet haben, während das zweite eine <Button> -Komponente verwendet hat. Die <Button> -Komponente wurde für Wiederverwendbarkeit gebaut und ist einfacher zu lesen, da sie eine bessere Semantik hat. Anstelle einer langen Liste von Klassennamen verwendet es Eigenschaften, um verschiedene Attribute wie size , textColor und bgColor .

Lass uns anfangen.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

Methode 1: Steuern von Klassen mit dem Classnames-Modul

Eine einfache Möglichkeit, Tailwind in eine React-Anwendung anzupassen, besteht darin, die Klassennamen zu übernehmen und sie programmgesteuert umzuschalten.

Das npm-Modul classnames erleichtert das Umschalten von Klassen in React. Um zu demonstrieren, wie Sie dies verwenden können, nehmen wir einen Anwendungsfall, in dem Sie <Button> -Komponenten in Ihrer React-Anwendung haben.

 // This could be hard to read. <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Enable</button> // This is more conventional React. <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>

Sehen wir uns an, wie man Tailwind-Klassen trennt, damit Benutzer dieser <Button> -Komponente React-Props wie size , textColor und bgColor .

  1. Übergeben Sie Requisiten wie bgColor und textColor direkt an die Zeichenfolgenvorlage für den Klassennamen.
  2. Verwenden Sie Objekte, um Klassennamen programmgesteuert zu wechseln (wie wir es mit dem size getan haben)

Im folgenden Beispielcode sehen wir uns beide Ansätze an.

 // Button.jsx import classnames from 'classnames'; function Button ({size, bgColor, textColor, children}) { return ( <button className={classnames("bg-${bgColor} text-${textColor} font-bold py-2 px-4 rounded", { "text-xs": size === 'sm' "text-xl": size === 'lg', })}> {children} </button> ) }; export default Button;

Im obigen Code definieren wir eine Button , die die folgenden Requisiten akzeptiert:

  • size
    Definiert die Größe des Buttons und wendet die Tailwind-Klassen text-xs oder text-xl an
  • bgColor
    Definiert die Hintergrundfarbe der Schaltfläche und wendet die Klassen Tailwind bg-* an.
  • textColor
    Definiert die Textfarbe der Schaltfläche und wendet die Tailwind-Text- text-* classes .
  • children
    Alle Unterkomponenten werden hier durchlaufen. Es enthält normalerweise den Text innerhalb des <Button> .

Durch die Definition von Button.jsx können wir es jetzt importieren und React-Props anstelle von Klassennamen verwenden. Dadurch ist unser Code leichter lesbar und wiederverwendbar.

 import Button from './Button'; <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>

Verwenden von Klassennamen für interaktive Komponenten

Ein Button ist ein sehr einfacher Anwendungsfall. Was ist mit etwas Komplizierterem? Nun, Sie können dies weiterführen, um interaktive Komponenten zu erstellen.

Sehen wir uns beispielsweise ein Dropdown-Menü an, das mit Tailwind erstellt wurde.


Ein interaktives Dropdown-Menü, das mithilfe von Tailwind und Umschalten des Klassennamens erstellt wurde.

Für dieses Beispiel erstellen wir die HTML-Komponente mit CSS-Klassennamen von Tailwind, stellen aber eine React-Komponente bereit, die so aussieht:

 <Dropdown options={\["Edit", "Duplicate", "Archive", "Move", "Delete"\]} onOptionSelect={(option) => { console.log("Selected Option", option)} } />

Wenn Sie sich den obigen Code ansehen, werden Sie feststellen, dass wir keine Tailwind-Klassen haben. Sie sind alle im Implementierungscode von <Dropdown/> versteckt. Der Benutzer dieser Dropdown Komponente muss lediglich eine Liste mit options und einen Klick-Handler bereitstellen, onOptionSelect , wenn auf eine option geklickt wird.

Sehen wir uns an, wie diese Komponente mit Tailwind erstellt werden kann.

Wenn Sie einen Teil des nicht verwandten Codes entfernen, ist hier der Kern der Logik. Sie können diesen Codepen für ein vollständiges Beispiel anzeigen.

 import classNames from 'classnames'; function Dropdown({ options, onOptionSelect }) { // Keep track of whether the dropdown is open or not. const [isActive, setActive] = useState(false); const buttonClasses = `inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-blue-500 active:text-gray-200 transition ease-in-out duration-150`; return ( // Toggle the dropdown if the button is clicked <button onClick={() => setActive(!isActive)} className={buttonClasses}> Options </button> // Use the classnames module to toggle the Tailwind .block and .hidden classes <div class={classNames("origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg", { block: isActive, hidden: !isActive })}> // List items are rendered here. {options.map((option) => <div key={option} onClick={(e) => onOptionSelect(option)}>{option}</div>)} </div> ) } export default Dropdown;

Das Dropdown wird interaktiv gemacht, indem es mithilfe der Klassen .hidden und .block selektiv angezeigt oder ausgeblendet wird. Immer wenn <button> gedrückt wird, feuern wir den onClick Handler ab, der den isActive -Zustand umschaltet. Wenn die Schaltfläche aktiv ist ( isActive === true ), setzen wir die block . Andernfalls setzen wir die hidden Klasse. Dies sind beide Tailwind-Klassen zum Umschalten des Anzeigeverhaltens.

Zusammenfassend ist das Modul classnames eine einfache und effektive Möglichkeit, Klassennamen für Tailwind programmgesteuert zu steuern. Es macht es einfacher, Logik in React-Requisiten zu trennen, was die Wiederverwendung Ihrer Komponenten erleichtert. Es funktioniert für einfache und interaktive Komponenten.

Methode 2: Verwenden von Konstanten zum Definieren eines Designsystems

Eine andere Möglichkeit, Tailwind und React zusammen zu verwenden, besteht darin, Konstanten zu verwenden und Requisiten einer bestimmten Konstante zuzuordnen. Dies ist für den Aufbau von Entwurfssystemen effektiv. Lassen Sie es uns anhand eines Beispiels demonstrieren.

Beginnen Sie mit einer theme.js -Datei, in der Sie Ihr Designsystem auflisten.

 // theme.js (you can call it whatever you want) export const ButtonType = { primary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", secondary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", basic: "bg-white hover:bg-gray-700 text-gray-700 font-bold rounded", delete: "bg-red-300 hover:bg-red-500 text-white font-bold rounded" }; export const ButtonSize = { sm: "py-2 px-4 text-xs", lg: "py-3 px-6 text-lg" }

In diesem Fall haben wir zwei Sätze von Konstanten:

  • ButtonType definiert, wie Schaltflächen in unserer App gestaltet werden.
  • ButtonSizes definiert die Größe der Schaltflächen in unserer App.

Lassen Sie uns nun unsere <Button> -Komponente schreiben:

 import {ButtonType, ButtonSize} from './theme'; function Button({size, type, children}) { // This can be improved. I'm keeping it simple here by joining two strings. const classNames = ButtonType[type] + " " + ButtonSize[size]; return ( <button className={classNames}>{children}</button> ) } export default Button;

Wir verwenden die Konstanten ButtonType und ButtonSize , um eine Liste mit Klassennamen zu erstellen. Das macht die Oberfläche unseres <Button> viel schöner. Es ermöglicht uns, size und type Requisiten zu verwenden, anstatt alles in einen Klassennamen-String zu packen.

 // Cleaner and well defined props. <Button size="xs" type="primary">Enable</Button>

Im Vergleich zum vorherigen Ansatz:

 // Exposing class names <button className="py-2 px-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Enable</button>

Wenn Sie das Aussehen von Schaltflächen in Ihrer Anwendung neu definieren müssen, bearbeiten Sie einfach die Datei theme.js und alle Schaltflächen in Ihrer App werden automatisch aktualisiert. Dies kann einfacher sein, als in verschiedenen Komponenten nach Klassennamen zu suchen.

Methode 3: Erstellen von Dienstprogrammen mit @apply

Eine dritte Möglichkeit, die Lesbarkeit Ihrer React-Komponenten zu verbessern, ist die Verwendung von CSS und dem @apply-Muster, das in @apply verfügbar ist, um wiederholte Klassen zu extrahieren. Dieses Muster beinhaltet die Verwendung von Stylesheets und Postprozessoren.

Lassen Sie uns anhand eines Beispiels demonstrieren, wie dies funktioniert. Angenommen, Sie haben eine Schaltflächengruppe mit einer primären und einer sekundären Schaltfläche.

Eine Schaltflächengruppe, die aus einer primären und einer sekundären Schaltfläche besteht
Eine Schaltflächengruppe, die aus einer primären und einer sekundären Schaltfläche besteht. (Große Vorschau)
 <button className="py-2 px-4 mr-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Update Now</button> <button className="py-2 px-4 text-xs mr-4 hover:bg-gray-100 text-gray-700 border-gray-300 border font-bold rounded">Later</button>

Mit dem @apply -Muster können Sie diesen HTML-Code wie folgt schreiben:

 <button className="btn btn-primary btn-xs">Update Now</button> <button className="btn btn-secondary btn-xs">Later</button>

Was dann an React angepasst werden kann, um zu werden:

 import classnames from "classnames"; function Button ({size, type, children}) { const bSize = "btn-" + size; const bType = "btn-" + type; return ( <button className={classnames("btn", bSize, bType)}>{children}</button> ) } Button.propTypes = { size: PropTypes.oneOf(['xs, xl']), type: PropTypes.oneOf(['primary', 'secondary']) }; // Using the Button component. <Button type="primary" size="xs">Update Now</Button> <Button type="secondary" size="xs">Later</Button>

So würden Sie diese Klassennamen im BEM-Stil wie .btn , .btn-primary und andere erstellen. Erstellen Sie zunächst eine button.css -Datei:

 /\* button.css \*/ @tailwind base; @tailwind components; .btn { @apply py-2 px-4 mr-4 font-bold rounded; } .btn-primary { @apply bg-blue-500 hover:bg-blue-700 text-white; } .btn-secondary { @apply hover:bg-gray-700 text-gray-700 border-gray-300 border; } .btn-xs { @apply text-xs; } .btn-xl { @apply text-xl; } @tailwind utilities;

Der obige Code ist kein echtes CSS, aber er wird von PostCSS kompiliert. Hier ist ein GitHub-Repository verfügbar, das zeigt, wie PostCSS und Tailwind für ein JavaScript-Projekt eingerichtet werden.

Es gibt auch ein kurzes Video, das zeigt, wie man es hier einrichtet.

Nachteile der Verwendung von @apply

Das Konzept, Tailwind-Hilfsklassen in CSS-Klassen höherer Ebene zu extrahieren, scheint sinnvoll zu sein, hat aber einige Nachteile, die Sie beachten sollten. Lassen Sie uns diese mit einem anderen Beispiel hervorheben.

Erstens gehen durch das Extrahieren dieser Klassennamen einige Informationen verloren. Beispielsweise müssen wir uns darüber im Klaren sein, dass .btn-primary zu einer Komponente hinzugefügt werden muss, auf die bereits .btn angewendet wurde. Außerdem können .btn-primary und .btn-secondary nicht zusammen angewendet werden. Diese Informationen sind nicht ersichtlich, wenn man sich nur die Klassen ansieht.

Wenn diese Komponente etwas komplizierter wäre, müssten Sie auch die Eltern-Kind-Beziehung zwischen den Klassen verstehen. In gewisser Weise ist dies das Problem, das Tailwind lösen sollte, und durch die Verwendung von @apply bringen wir die Probleme auf andere Weise zurück.

Hier ist ein Video, in dem Adam Wathan – der Schöpfer von Tailwind – in die Vor- und Nachteile der Verwendung von @apply .

Zusammenfassung

In diesem Artikel haben wir uns drei Möglichkeiten angesehen, wie Sie Tailwind in eine React-Anwendung integrieren können, um wiederverwendbare Komponenten zu erstellen. Diese Methoden helfen Ihnen dabei, React-Komponenten zu erstellen, die mithilfe von props eine übersichtlichere Oberfläche haben.

  1. Verwenden Sie das Modul classnames, um Klassen programmgesteuert umzuschalten.
  2. Definieren Sie eine Konstantendatei, in der Sie eine Liste von Klassen pro Komponentenstatus definieren.
  3. Verwenden Sie @apply , um CSS-Klassen auf höherer Ebene zu extrahieren.

Wenn Sie Fragen haben, senden Sie mir eine Nachricht auf Twitter unter @tilomitra.

Empfohlene Lektüre auf SmashingMag:

  • Einrichten von Tailwind CSS in einem React-Projekt
  • Erstellen von sortierbaren Tabellen mit React
  • Ein Leitfaden für neue und experimentelle CSS-Entwicklungstools in Firefox
  • Erstellen Sie Ihre eigenen erweiternden und zusammenziehenden Inhaltsfelder