Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V tomto kurzu vytvoříte front-end Reactu pro webovou aplikaci se seznamem to-do pomocí JavaScriptu a sady Visual Studio 2022. Kód pro tuto aplikaci najdete v ToDoJSWebApp.
Požadavky
Nezapomeňte nainstalovat následující:
- Visual Studio 2022 nebo novější Přejděte na stránku ke stažení Visual Studio a nainstalujte si ho zdarma.
- npm (
https://www.npmjs.com/), který je součástí Node.js.
Vytvoření aplikace React ToDo List
V sadě Visual Studio vyberte Soubor > Nový > Projekt pro otevření dialogového okna Vytvořit nový projekt, vyberte šablonu React App JavaScript a pak zvolte Další.
Pojmenujte projekt
TodoWebAppa vyberte Vytvořit.Tím se vytvoří projekt JavaScriptu pomocí nástroje příkazového řádku vite.
V Průzkumníku řešení klikněte pravým tlačítkem myši na složku
srca zvolte Přidat > Novou složku. a vytvořte novou složku s názvemcomponents.Je to běžná konvence pro umístění součástí do složky komponent, ale nevyžaduje se to.
Klikněte pravým tlačítkem myši na novou složku, vyberte Přidat > novou položku a v dialogovém okně zvolte React JSX Component File , pojmenujte ji
TodoLista klikněte na Přidat. Pokud seznam šablon položek nevidíte, vyberte Zobrazit všechny šablony.
Tím se vytvoří nový soubor JSX ve složce komponent.
Otevřete komponentu
TodoLista nahraďte výchozí obsah následujícím kódem:function TodoList() { return ( <h2>TODO app contents</h2> ); } export default TodoList;Tato komponenta zobrazí hlavičku, kterou později nahradíte.
Dále tuto komponentu v aplikaci propojte. Komponenta
App.jsxje hlavní součást, která je načtená a představuje aplikaci seznamu to-do. Tato komponenta se používá v souborumain.jsx.V Průzkumníku řešení otevřete
App.jsx, odeberte všechny importy z horní části a vymažte obsah příkazu return. Soubor by měl vypadat takto.function App() { return ( <> <TodoList /> </> ); } export default App;Chcete-li přidat komponentu TodoList, umístěte kurzor do fragmentu a zadejte
<TodoL RETURNnebo<TodoL TAB. Tím se přidá komponenta. Může také automaticky přidat příkaz importu.
aplikace
Pokud se příkaz importu nepřidá automaticky, přidejte ho na začátek souboru zadáním
import TodoLa stisknutím klávesy TAB .V dalším kroku vymažte soubory CSS.
Otevřete
App.cssa odstraňte veškerý obsah.Otevřete
Index.cssa odeberte veškerý obsah kromě stylů pro:root::root { font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; line-height: 1.5; font-weight: 400; color-scheme: light dark; color: rgba(255, 255, 255, 0.87); background-color: #242424; }
Spuštění aplikace
Na panelu nástrojů vyberte tlačítko Spustit ladění nebo stiskněte klávesovou zkratku F5.
Aplikace se otevře v okně prohlížeče.
Přidání funkcí seznamu to-do do aplikace
Aplikaci můžete nechat spuštěnou. Při provádění změn se aplikace automaticky aktualizuje s nejnovějším obsahem pomocí podpory nahrazení horkého modulu Vite. Některé akce, jako je přidání složek nebo přejmenování souborů, vyžadují, abyste zastavili ladění a pak aplikaci restartovali, ale obecně ji můžete nechat spuštěnou na pozadí při vývoji aplikace. Otevřete komponentu TodoList.jsx, abychom ji mohli začít definovat.
V Průzkumníku řešení otevřete
TodoList.jsxa přidejte uživatelské rozhraní potřebné k zobrazení a správě položek seznamu to-do. Nahraďte obsah následujícím kódem:function TodoList() { return ( <div> <h1>TODO</h1> <div> <input type="text" placeholder="Enter a task" required aria-label="Task text" /> <button className="add-button" aria-label="Add task">Add</button> </div> <ol id="todo-list"> <p>existing tasks will be shown here</p> </ol> </div> ); } export default TodoList;Předchozí kód přidá vstupní pole pro nový to-do úkol a tlačítko pro odeslání vstupu. Nyní propojte tlačítko Přidat. Pomocí funkce useState React hook přidejte dvě stavové proměnné, jednu pro úkol, který se přidává, a další pro uložení existujících úkolů. Pro účely tohoto kurzu se úlohy ukládají v paměti a ne trvalé úložiště.
Přidejte následující příkaz importu pro
TodoList.jsxpro importuseState.import { useState } from 'react'Dále pomocí tohoto háku vytvořte stavové proměnné. Do funkce
TodoListnad příkaz return přidejte následující kód.const [tasks, setTasks] = useState(["Drink some coffee", "Create a TODO app", "Drink some more coffee"]); const [newTaskText, setNewTaskText] = useState("");Tím se nastaví dvě proměnné,
tasksanewTaskText, pro data a dvě funkce, které můžete volat k aktualizaci těchto proměnných,setTasksasetNewTasks. Když se změní hodnota stavu proměnné, React automaticky znovu vykreslí komponentu.Téměř jste připraveni aktualizovat TodoList.jsx, abyste zobrazili to-do položky jako seznam, ale nejprve je důležité pochopit důležitý koncept Reactu.
Když v Reactu zobrazíte seznam položek, musíte přidat klíč, který jedinečně identifikuje jednotlivé položky v seznamu. Tato funkce je podrobně vysvětlená v dokumentaci Reactu v vykreslovacích seznamech, ale tady se seznámíte se základy. Máte seznam to-do položek, které se mají zobrazit, a potřebujete pro každou položku přidružit jedinečný klíč. Klíč pro každou položku by se neměl měnit a z tohoto důvodu nemůžete jako klíč použít index položky v poli. Potřebujete ID, které se po celou dobu životnosti těchto hodnot nezmění. K vytvoření jedinečného ID pro každou položku to-do použijete randomUUID().
Vytvořte TodoList.jsx pomocí UUID jako klíče pro každou položku to-do. Aktualizujte todoList.jsx následujícím kódem.
import React, { useState } from 'react'; const initialTasks = [ { id: self.crypto.randomUUID(), text: 'Drink some coffee' }, { id: self.crypto.randomUUID(), text: 'Create a TODO app' }, { id: self.crypto.randomUUID(), text: 'Drink some more coffee' } ]; function TodoList() { const [tasks, setTasks] = useState(initialTasks); const [newTaskText, setNewTaskText] = useState(""); return ( <article className="todo-list" aria-label="task list manager"> <header> <h1>TODO</h1> <form className="todo-input" aria-controls="todo-list"> <input type="text" placeholder="Enter a task" value={newTaskText} /> <button className="add-button"> Add </button> </form> </header> <ol id="todo-list" aria-live="polite" aria-label="task list"> {tasks.map((task, index) => <li key={task.id}> <span className="text">{task.text}</span> </li> )} </ol> </article> ); } export default TodoList;Vzhledem k tomu, že jsou hodnoty ID přiřazeny mimo funkci TodoList, můžete mít jistotu, že se hodnoty při opětovném vykreslení stránky nezmění. Když aplikaci vyzkoušíte v tomto stavu, všimnete si, že do vstupního elementu todo nemůžete zadávat. Důvodem je to, že vstupní prvek je vázán na
newTaskText, který byl inicializován na prázdný řetězec. Pokud chcete uživatelům povolit přidávání nových úkolů, musíte na daném ovládacím prvku zpracovatonChangeudálost. Musíte také implementovat podporu tlačítka Přidat.Přidejte požadované funkce bezprostředně před příkaz return ve funkci TodoList.
function handleInputChange(event) { setNewTaskText(event.target.value); } function addTask() { if (newTaskText.trim() !== "") { setTasks(t => [...t, { id: self.crypto.randomUUID(), text: newTaskText }]); setNewTaskText(""); } event.preventDefault(); }Ve funkci
handleInputChangedse nová hodnota ze vstupního pole předává prostřednictvímevent.target.valuea tato hodnota slouží k aktualizaci hodnoty proměnnénewTaskTextpomocísetNewTaskText. Ve funkciaddTaskpřidejte nový úkol do seznamu existujících úkolů pomocísetTasksa nastavte ID položky jako novou hodnotu UUID. Aktualizujte vstupní prvek tak, aby zahrnovalonChange={handleInputChange}a aktualizujte tlačítko Přidat tak, aby zahrnovaloonClick={addTask}. Tento kód propojí událost s funkcí, která ji zpracovává. Za tímto účelem byste měli být schopni do seznamu úkolů přidat nový úkol. Nové úkoly se přidají do dolní části seznamu. Aby byla tato aplikace užitečnější, musíte přidat podporu pro odstranění úkolů a přesunout úkol nahoru nebo dolů.Přidejte funkce pro podporu odstranění, přesunutí nahoru a přesunutí dolů, a pak aktualizujte označení tak, aby zobrazovalo tlačítko pro každou akci. Do funkce TodoList nad příkaz return přidejte následující kód.
function deleteTask(id) { const updatedTasks = tasks.filter(task => task.id != id); setTasks(updatedTasks); } function moveTaskUp(index) { if (index > 0) { const updatedTasks = [...tasks]; [updatedTasks[index], updatedTasks[index - 1]] = [updatedTasks[index - 1], updatedTasks[index]]; setTasks(updatedTasks); } } function moveTaskDown(index) { if (index < tasks.length) { const updatedTasks = [...tasks]; [updatedTasks[index], updatedTasks[index + 1]] = [updatedTasks[index + 1], updatedTasks[index]]; setTasks(updatedTasks); } }Funkce delete převezme ID úlohy a odstraní ji ze seznamu a pomocí metody Array filter() vytvoří nové pole s výjimkou vybrané položky a potom zavolá
setTasks(). Ostatní dvě funkce přebírají index položky, protože tato práce je specifická pro řazení položek.moveTaskUp()imoveTaskDown()používají destrukturalizaci přiřazení pole pro prohození vybraného úkolu se sousedem.V dalším kroku aktualizujte zobrazení tak, aby zahrnovalo tyto tři tlačítka. Aktualizujte návratový příkaz tak, aby obsahoval následující.
return ( <article className="todo-list" aria-label="task list manager"> <header> <h1>TODO</h1> <form className="todo-input" onSubmit={addTask} aria-controls="todo-list"> <input type="text" required autoFocus placeholder="Enter a task" value={newTaskText} aria-label="Task text" onChange={handleInputChange} /> <button className="add-button" aria-label="Add task"> Add </button> </form> </header> <ol id="todo-list" aria-live="polite"> {tasks.map((task, index) => <li key={task.id}> <span className="text">{task.text}</span> <button className="delete-button" onClick={() => deleteTask(task.id)}> 🗑️ </button> <button className="up-button" onClick={() => moveTaskUp(index)}> ⇧ </button> <button className="down-button" onClick={() => moveTaskDown(index)}> ⇩ </button> </li> )} </ol> </article> );Přidali jste tlačítka potřebná k provedení dříve probíraných úloh. Znaky Unicode používáte jako ikony na tlačítkách. V kódu jsou přidány některé atributy pro podporu pozdějšího přidání některých šablon stylů CSS. Můžete si také všimnout použití atributů aria ke zlepšení přístupnosti, které jsou volitelné, ale důrazně doporučujeme. Pokud aplikaci spustíte, měla by vypadat jako na následujícím obrázku.
Teď byste měli být schopni ve webové aplikaci TODO provést následující.
- Přidat úkol
- Odstranit úkol
- Přesunout úkol nahoru
- Přesunout úkol dolů
Tyto funkce fungují, ale můžete refaktorovat k vytvoření opakovaně použitelné komponenty pro zobrazení to-do položek. Kód položky to-do přejde do nové komponenty TodoItem. Jelikož správa seznamu zůstává v komponentě Todo, můžete k tlačítkům Odstranit a Přesunout předat funkce zpětného volání.
Začněte tak, že v Průzkumníku řešení kliknete pravým tlačítkem na složku komponent a vyberete Přidat > Nová položka.
V dialogovém okně, které se otevře, vyberte React JSX Component File, pojmenujte ho TodoItem a vyberte Přidat.
Do todoItem přidejte následující kód.
V tomto kódu předáte úlohu a zpětná volání jako vlastnosti této nové součásti.
import PropTypes from 'prop-types'; function TodoItem({ task, deleteTaskCallback, moveTaskUpCallback, moveTaskDownCallback }) { return ( <li aria-label="task" > <span className="text">{task}</span> <button type="button" aria-label="Delete task" className="delete-button" onClick={() => deleteTaskCallback()}> 🗑️ </button> <button type="button" aria-label="Move task up" className="up-button" onClick={() => moveTaskUpCallback()}> ⇧ </button> <button type="button" aria-label="Move task down" className="down-button" onClick={() => moveTaskDownCallback()}> ⇩ </button> </li> ); } TodoItem.propTypes = { task: PropTypes.string.isRequired, deleteTaskCallback: PropTypes.func.isRequired, moveTaskUpCallback: PropTypes.func.isRequired, moveTaskDownCallback: PropTypes.func.isRequired, }; export default TodoItem;Předchozí kód obsahuje kód ze komponenty Todo a na konci deklarujete
PropTypes. Props se používají k předávání dat z nadřazené komponenty do podřízených komponent. Další informace o props naleznete v tématu Předávání props komponentě – React. Vzhledem k tomu, že funkce delete a move se předávají jako zpětná volání, musí být obslužná rutinaonClickaktualizována, aby mohla tyto zpětná volání vyvolat.Přidejte požadovaný kód. Zde je uveden úplný kód pro TodoList, který používá komponentu TodoItem.
import React, { useState } from 'react' import TodoItem from './TodoItem' const initialTasks = [ { id: self.crypto.randomUUID(), text: 'Drink some coffee' }, { id: self.crypto.randomUUID(), text: 'Create a TODO app' }, { id: self.crypto.randomUUID(), text: 'Drink some more coffee' } ]; function TodoList() { const [tasks, setTasks] = useState(initialTasks); const [newTaskText, setNewTaskText] = useState(""); function handleInputChange(event) { setNewTaskText(event.target.value); } function addTask() { if (newTaskText.trim() !== "") { setTasks(t => [...t, { id: self.crypto.randomUUID(), text: newTaskText }]); setNewTaskText(""); } event.preventDefault(); } function deleteTask(id) { const updatedTasks = tasks.filter(task => task.id !== id); setTasks(updatedTasks); } function moveTaskUp(index) { if (index > 0) { const updatedTasks = [...tasks]; [updatedTasks[index], updatedTasks[index - 1]] = [updatedTasks[index - 1], updatedTasks[index]]; setTasks(updatedTasks); } } function moveTaskDown(index) { if (index < tasks.length) { const updatedTasks = [...tasks]; [updatedTasks[index], updatedTasks[index + 1]] = [updatedTasks[index + 1], updatedTasks[index]]; setTasks(updatedTasks); } } return ( <article className="todo-list" aria-label="task list manager"> <header> <h1>TODO</h1> <form onSubmit={addTask} aria-controls="todo-list"> <input type="text" required placeholder="Enter a task" value={newTaskText} aria-label="Task text" onChange={handleInputChange} /> <button className="add-button" aria-label="Add task"> Add </button> </form> </header> <ol id="todo-list" aria-live="polite"> {tasks.map((task, index) => <TodoItem key={task.id} task={task.text} deleteTaskCallback={() => deleteTask(task.id)} moveTaskUpCallback={() => moveTaskUp(index)} moveTaskDownCallback={() => moveTaskDown(index)} /> )} </ol> </article> ); } export default TodoList;Nyní se komponenta TodoItem používá k vykreslení každé to-do položky. Všimněte si, že klíč je nastavený na
task.id, který obsahuje hodnotu UUID pro daný úkol. Při spuštění aplikace byste neměli vidět žádné změny vzhledu nebo chování aplikace, protože jste ji refaktorovali tak, aby používala TodoItem.Teď, když máte všechny základní funkce podporované, je čas začít do toho přidávat nějaký styl, aby vypadal hezky. Začněte přidáním odkazu v Index.html pro rodinu písem Inter, kterou použijete pro tuto aplikaci. V Index.htmljsou některé další položky, které je potřeba vyčistit. Konkrétně by se měl název aktualizovat a chcete nahradit vite.svg soubor, který se aktuálně používá jako ikona.
Aktualizujte Index.html následujícím obsahem.
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/checkmark-square.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>TODO app</title> <link href='https://fonts.googleapis.com/css?family=Inter' rel='stylesheet'> <script type="module" defer src="/src/main.jsx"></script> </head> <body> </body> </html>Upravte soubor main.jsx tak, aby při volání
rootnahradilmaincreateRoot.Tady je uvedený úplný kód pro main.jsx.
import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import App from './App.jsx' import './index.css' createRoot(document.querySelector('main')).render( <StrictMode> <App /> </StrictMode>, )Kromě těchto změn se soubor checkmark-square.svg přidal do veřejné složky. Toto je SVG obrázek značky zaškrtnutí ve tvaru čtverce z FluentUI, který si můžete stáhnout přímo. (Existuje balíček, který můžete použít pro integrovanější prostředí, ale to je mimo rozsah tohoto článku.)
Dále aktualizujte styly komponenty TodoList.
Do složky komponent přidejte nový soubor CSS s názvem TodoList.css. Můžete kliknout pravým tlačítkem myši na projekt a vybrat Přidat > Nová položka a pak vybrat šablonu stylů. Zadejte název souboru TodoList.css.
Do TodoList.csspřidejte následující kód.
.todo-list { background-color: #1e1e1e; padding: 1.25rem; border-radius: 0.5rem; box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.3); width: 100%; max-width: 25rem; } .todo-list h1 { text-align: center; color: #e0e0e0; } .todo-input { display: flex; justify-content: space-between; margin-bottom: 1.25rem; } .todo-input input { flex: 1; padding: 0.625rem; border: 0.0625rem solid #333; border-radius: 0.25rem; margin-right: 0.625rem; background-color: #2c2c2c; color: #e0e0e0; } .todo-input .add-button { padding: 0.625rem 1.25rem; background-color: #007bff; color: #fff; border: none; border-radius: 0.25rem; cursor: pointer; } .todo-input .add-button:hover { background-color: #0056b3; } .todo-list ol { list-style-type: none; padding: 0; } .todo-list li { display: flex; justify-content: space-between; align-items: center; padding: 0.625rem; border-bottom: 0.0625rem solid #333; } .todo-list li:last-child { border-bottom: none; } .todo-list .text { flex: 1; } .todo-list li button { background: none; border: none; cursor: pointer; font-size: 1rem; margin-left: 0.625rem; color: #e0e0e0; } .todo-list li button:hover { color: #007bff; } .todo-list li button.delete-button { color: #ff4d4d; } .todo-list li button.up-button, .todo-list li button.down-button { color: #4caf50; }Dále upravte TodoList.jsx a přidejte do horní části souboru následující import.
import './TodoList.css';Po uložení změn aktualizujte prohlížeč. Tím by se měl zlepšit styl aplikace. Aplikace by měla vypadat nějak takto.
Teď jste vytvořili funkční aplikaci seznamu to-do, která ukládá položky to-do do paměti. Od tohoto okamžiku byste mohli aplikaci aktualizovat tak, aby ukládaly to-do položky v localStorage/IndexedDb, nebo ji integrovala s databází na straně serveru nebo s jiným back-endem pro trvalejší úložiště.
Shrnutí
V tomto kurzu jste pomocí sady Visual Studio vytvořili novou aplikaci React. Aplikace se skládá ze seznamu to-do, který zahrnuje podporu pro přidávání úkolů, odstraňování úkolů a jejich uspořádání. Vytvořili jste dvě nové komponenty React a použili jste je v tomto kurzu.
Prostředky
- Kód pro tuto ukázku na ToDoJSWebApp
- Projekty JavaScript a TypeScript pro Visual Studio