Einrichtung:
Vite-Einrichtung
Wir werden unser Projekt mit Vite einrichten. Dafür schreiben wir den folgenden Befehl:
npm create vite@latest
Nachdem wir dies eingegeben haben, werden wir im Terminal nach dem Namen des Projekts gefragt; unser Projektname ist "nobel-pen".
Dann geben wir an, in welcher Umgebung wir es einrichten werden: Es ist ein React-Projekt und JavaScript+SWC.
cd nobel-pen
npm install
npm run dev
Wir betreten unser Projekt, installieren npm und führen es aus.
Relevanter GitHub-Repository-Link: https://github.com/sanscodex/nobel-pen/tree/c2120b98e2413d3d4a90f4b5aa1e70c0eb485d96
Tailwind CSS-Einrichtung
Da wir unser Projekt bereits erstellt haben, laden wir bei der Tailwind-Installation nur die Abhängigkeiten herunter.
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Installieren Sie tailwindcss und seine Abhängigkeiten, erstellen Sie dann Ihre tailwind.config.js und postcss.config.js Dateien. Fügen Sie in Ihrer tailwind.config.js-Datei die Pfade zu all Ihren Vorlagendateien hinzu.
/** @type {import('tailwindcss').Config} */
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};
Fügen Sie die @tailwind-Direktiven für jede der Tailwind-Schichten zu Ihrer ./src/index.css-Datei hinzu.
@tailwind base;
@tailwind components;
@tailwind utilities;
Relevanter GitHub-Repository-Link: https://github.com/sanscodex/nobel-pen/tree/4253ba50493200aefeb239aca138e7dca7b3c47a
Mock-Daten
Wir haben Mock-Daten von Autoren hinzugefügt, die den Nobelpreis für Literatur erhalten haben. Lassen Sie uns einen der Autoren als Beispiel zeigen.
{
id: "241248",
name: "Orhan Pamuk",
year: "2006",
imageUrl:
"https://commons.wikimedia.org/wiki/Special:FilePath/Orhan%20Pamuk%202009%20Shankbone.jpg",
wiki: "https://en.wikipedia.org/wiki/Orhan_Pamuk",
countries: "Turkey",
notableWorks:
"The Museum of Innocence, The New Life, The Black Book, My Name Is Red, Istanbul: Memories and the City, Cevdet Bey and His Sons, Snow, The White Castle, Nights of Plague",
},
Relevanter GitHub-Repository-Link: https://github.com/sanscodex/nobel-pen/tree/c43517945c47d6dc1c4121458e605015250eab1c
Vorbereitung des Projektgerüsts
Zunächst werden wir unsere Komponenten unter src erstellen; unsere erste Komponente ist Header.
import Logo from "../assets/nobel-prize-logo.png";
const Header = () => {
return (
<div className="flex justify-around items-center mt-16">
<img src={Logo} alt="logo" className="w-32"></img>
<h1 className="text-center text-2xl w-40 text-yellow-300">
<span className="text-6xl">Nobel</span>{" "}
<span className="text-5xl">Prizes</span> in Literature
</h1>
</div>
);
};
export default Header;
Hier schreiben wir einen Header mit unserem Logo und Titel. Ich lege das Logo in die Assets unter src und rufe es beim Aufrufen mit import auf, wobei wir auch die Bilderweiterung angeben. Diese Header-Komponente senden wir in App.jsx.
Wir schreiben auch die Komponente, in der wir die Suche durchführen werden, und importieren sie in App.jsx.
const Search = () => {
return (
<div className="flex justify-center mt-16">
<input
type="text"
placeholder="Search Author"
className="w-96 p-4 bg-yellow-400 text-black"
/>
</div>
);
};
export default Search;
Lasst uns anfangen, Authors.jsx zu schreiben, in dem wir die mit dem Nobelpreis ausgezeichneten Autoren aus den Daten abrufen werden.
Da data ein benannter Export ist, können wir den Namen beim Import nicht ändern. Wir können es nur so importieren, wie es geschrieben wurde.
import { data } from "../helpers/data";
const Authors = () => {
console.log(data);
return (
<div className="authors-container">
<div className="author-card">
<div className="author-image">
<img src="#" alt="author-name" />
</div>
<div className="author-info">
<p>Author Name</p>
<p>Notable Books</p>
<p>Nobel's year</p>
<p>Author's Country</p>
<button>Read More in Wiki</button>
</div>
</div>
</div>
);
};
export default Authors;
Zunächst zeige ich die Autoren mit diesen Karten an. Außerdem können wir alle unsere Daten in der Konsole wie folgt sehen.
Logische Teile des Projekts
Lass uns ein wenig Stil mit Tailwind hinzufügen. Ich mappe die Autoren, erstelle für jeden eingehenden Datensatz eine neue Karte und platziere die als Parameter eingehenden Daten an den entsprechenden Stellen auf den Karten. Und lass uns einen ternären Operator mit useState verwenden. Wenn auf die Bildkarten geklickt wird, sollen die Informationen über den Autor angezeigt werden.
import { data } from "../helpers/data";
import { useState } from "react";
const Authors = () => {
console.log(data);
const [show, setShow] = useState(false);
return (
<div className="authors-container flex flex-row flex-wrap justify-center items-center gap-16 m-8">
{data.map((authorItem) => {
return (
<div
onClick={() => {
setShow(!show);
}}
key={authorItem.id}
className="author-card flex border w-80 border-yellow-400 p-4 gap-4"
>
{!show ? (
<div className="author-image w-72 overflow-hidden bg-slate-400 ">
<img
className="object-cover h-72 w-full"
src={authorItem.imageUrl}
alt={authorItem.name}
/>
<a className="border border-yellow-400 p-2 block text-yellow-400 font-bold text-xl text-center">
{authorItem.name}
</a>
</div>
) : (
<div className="author-info flex flex-col w-full gap-8">
<p>{authorItem.name}</p>
<p>{authorItem.notableWorks}</p>
<p>{authorItem.year}</p>
<p>{authorItem.countries}</p>
<a
href={authorItem.wiki}
className="p-2 w-32 bg-yellow-400 text-slate-800"
>
Read More
</a>
</div>
)}
</div>
);
})}
</div>
);
};
export default Authors;
Hier haben wir im ternären Operator gesagt, wenn der State falsch ist, wandle ihn mit dem not-Operator in wahr um und gib das Bild auf dem Bildschirm aus. Andernfalls gib die Autorinformationen auf dem Bildschirm aus. Da der Anfangswert des ersten State falsch ist, erscheinen die Bilder auf dem Bildschirm. Wir haben dies für jedes Element innerhalb der Map gemacht. Wenn auf die Karte geklickt wird, wird die onClick-Funktion aktiviert und aktualisiert den setShow-State so, dass er das Gegenteil des show-State ist.
Relevanter GitHub-Repository-Link: https://github.com/sanscodex/nobel-pen/tree/0f0c71c552fb3049c7b8e1d02ab5a2e3c5a473e1
Jetzt ändern sich hier alle Karten, wenn man auf eine Karte klickt. Wir müssen nur die angeklickte Karte ändern und ihre Informationen anzeigen. Das Problem hier ist, dass es nur einen State gibt, der die Änderung verfolgt; das heißt, wenn sich einer ändert, ändern sich alle Karten. Aber ich habe 122 verschiedene Karten. Das bedeutet, wir brauchen einen separaten State für jede Karte. Lasst uns den Teil, in dem die Autorinformationen angezeigt werden, zu einer separaten Komponente machen und dort useState verwenden. Auf diese Weise gibt es für jede einen separaten Klickzustand. Das Virtual DOM erkennt den Unterschied und aktualisiert nur die Komponente, die sich geändert hat. Daher erstellen wir eine separate Komponente für jeden Autor.
import { useState } from "react";
const Author = ({ authorItem }) => {
const [show, setShow] = useState(false);
return (
<>
<div
key={authorItem.id}
onClick={() => {
setShow(!show);
}}
className="author-card flex border w-80 border-yellow-400 p-4 gap-4"
>
{!show ? (
<div className="author-image w-72 overflow-hidden bg-slate-400 ">
<img
className="object-cover h-72 w-full"
src={authorItem.imageUrl}
alt={authorItem.name}
/>
<a className="border border-yellow-400 p-2 block text-yellow-400 font-bold text-xl text-center">
{authorItem.name}
</a>
</div>
) : (
<div className="author-info flex flex-col w-full gap-8">
<p>{authorItem.name}</p>
<p>{authorItem.notableWorks}</p>
<p>{authorItem.year}</p>
<p>{authorItem.countries}</p>
<a
href={authorItem.wiki}
className="p-2 w-32 bg-yellow-400 text-slate-800"
>
Read More
</a>
</div>
)}
</div>
</>
);
};
export default Author;
Hier verwenden wir useState für einen einzelnen Autor. Auf diese Weise öffnet sich die Karte, auf die wir klicken, und die Autorinformationen werden angezeigt.
import { data } from "../helpers/data";
import { useState } from "react";
import Author from "./Author";
const Authors = () => {
console.log(data);
return (
<div className="authors-container flex flex-row flex-wrap justify-center items-center gap-16 m-8">
{data.map((authorItem) => (
<Author key={authorItem.id} authorItem={authorItem} />
))}
</div>
);
};
export default Authors;
Hier mappen wir die Author Card-Komponente und geben jede einzeln aus.
Relevanter GitHub-Repository-Link: https://github.com/sanscodex/nobel-pen/tree/fd3af82559f85ea42d889569bd720c0f53fce6d8
Jetzt muss ich einen Filter auf die Suchschaltfläche anwenden.
Unsere Dateihierarchie ruft alles separat in App.jsx auf, daher werde ich useState oben in App.jsx definieren. Hier werde ich die handleChange-Änderung vornehmen. Ich werde diese Änderungen als Props nach unten senden.
import Authors from "./components/Authors";
import Header from "./components/Header";
import Search from "./components/Search";
import { useState } from "react";
export default function App() {
const [search, setSearch] = useState("");
const handleChange = (e) => {
setSearch(e.target.value);
};
return (
<div>
<Header />
<Search handleChange={handleChange} />
<Authors search={search} />
</div>
);
}
import Authors from "./components/Authors";
import Header from "./components/Header";
import Search from "./components/Search";
import { useState } from "react";
Diese Zeilen importieren die erforderlichen Komponenten und den useState-Hook von React.
export default function App() {
Dies definiert die Haupt-App-Komponente.
const [search, setSearch] = useState("");
Hier wird ein useState für den Suchbegriff erstellt. Der Anfangswert ist ein leerer String.
const handleChange = (e) => {
setSearch(e.target.value);
};
Diese Funktion fängt Änderungen in der Sucheingabe ab und aktualisiert den search state.
return (
<div>
<Header />
<Search handleChange={handleChange} >
<Authors search={search} >
</div>
);
Dieser Teil definiert die zu rendernde Struktur der Komponente. Er enthält die Komponenten Header, Search und Authors. Die handleChange-Funktion wird als Props an die Search-Komponente übergeben, und der search wird als Props an die Authors-Komponente übergeben.
Diese Struktur verwaltet die Suchfunktionalität auf der obersten Ebene (in der App-Komponente) und gibt die notwendigen Daten und Funktionen als Props an die untergeordneten Komponenten weiter. Dies ist ein Ansatz, der dem React-Prinzip des "Datenflusses von oben nach unten" entspricht.
import { useState } from "react";
const Search = (props) => {
return (
<div className="flex justify-center mt-16">
<input
type="text"
placeholder="Search Author"
className="w-96 p-4 bg-yellow-400 text-black"
onChange={props.handleChange}
/>
</div>
);
};
export default Search;
Dieser Codeabschnitt definiert eine Suchkomponente (Search component) mit React. Hier ist eine detaillierte Erklärung des Codes:
const Search = (props) => { ... }
Definiert eine Funktionskomponente namens Search. Diese Komponente akzeptiert einen Parameter namens props.
- Die Komponente gibt ein <div> Element zurück:
- <div> enthält ein Input-Element:
- onChange={props.handleChange} - Legt die Funktion fest, die aufgerufen wird, wenn sich der Wert des Inputs ändert. Diese Funktion wird über props von der übergeordneten Komponente weitergegeben.
- export default Search; - Exportiert die Search-Komponente, so dass sie in anderen Dateien importiert werden kann.
Diese Komponente erstellt ein Eingabefeld, in dem der Benutzer nach Autoren suchen kann. Wenn der Benutzer etwas in dieses Feld eingibt, wird die handleChange-Funktion aus der übergeordneten Komponente aufgerufen und die Suche durchgeführt.
import { data } from "../helpers/data";
import Author from "./Author";
const Authors = (props) => {
console.log(data);
const filteredData = data.filter((item) =>
item.name.toLowerCase().includes(props.search.toLowerCase())
);
return (
<div className="authors-container flex flex-row flex-wrap justify-center items-center gap-16 m-8">
{filteredData.map((authorItem, index) => (
<Author key={index} authorItem={authorItem} />
))}
</div>
);
};
export default Authors;
- Zunächst werden die erforderlichen Module und Komponenten importiert:
import { data } from "../helpers/data";
import Author from "./Author";
- Eine Funktionskomponente namens Authors wird definiert:
const Authors = (props) => {
// ...
};
- Eine Variable namens filteredData wird erstellt. Diese Variable filtert das data-Array:
const filteredData = data.filter((item) =>
item.name.toLowerCase().includes(props.search.toLowerCase())
);
Dieser Filtervorgang wählt Autorennamen aus, die den Wert von props.search (der vom Benutzer eingegebene Suchbegriff) enthalten. Dies ändert oben in App.jsx in handleChange den search in useState jedes Mal, wenn sich in Search.jsx etwas ändert, und sendet es als Props an Authors.jsx. toLowerCase() wird verwendet, um die Groß-/Kleinschreibung zu ignorieren.
- Das filteredData-Array wird mit der map()-Funktion durchlaufen:
{filteredData.map((authorItem, index) => (
<Author key={index} authorItem={authorItem} />
))}
Diese Schleife erstellt für jeden gefilterten Autor eine Author-Komponente. Jeder Author-Komponente werden die entsprechenden Autorendaten als authorItem-Props übergeben. Der index wird als key-Props verwendet.
- Schließlich wird die Authors-Komponente exportiert:
export default Authors;
Dieser Code erstellt eine Autorenliste mit Suchfunktion. Wenn ein Benutzer einen Suchbegriff eingibt, wird die Liste dynamisch gefiltert und zeigt nur die Autoren an, die dem Suchbegriff entsprechen.
Relevanter GitHub-Link: https://github.com/sanscodex/nobel-pen/tree/abb5a450238340fc25408486abaeb861196f274b
In diesem Projekt verwendete React-Funktionen: Projekterstellung mit Vite, Funktionskomponenten, useState-Hook, Props, Listenrendering mit der map-Funktion und bedingtes Rendering (unter Verwendung des ternären Operators).
— Github Repo
— Demo
Kommentar hinterlassen