Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym samouczku utworzysz interfejs użytkownika React dla aplikacji internetowej listy to-do za pomocą języka JavaScript i Visual Studio 2022. Kod tej aplikacji można znaleźć na stronie ToDoJSWebApp.
Warunki wstępne
Upewnij się, że zainstalowano następujące elementy:
- Program Visual Studio 2022 lub nowszy. Przejdź do strony pobierania programu Visual Studio, aby zainstalować ją bezpłatnie.
- npm (
https://www.npmjs.com/), który jest dołączony do Node.js.
Tworzenie aplikacji React ToDo List
W programie Visual Studio wybierz pozycję Plik > Nowy > Projekt, aby otworzyć okno dialogowe Tworzenie nowego projektu, wybierz szablon React App JavaScript, a następnie wybierz Dalej.
Nadaj projektowi nazwę
TodoWebAppi wybierz pozycję Utwórz.Spowoduje to utworzenie projektu JavaScript przy użyciu narzędzia wiersza polecenia vite.
W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy folder
srci wybierz pozycję Dodaj > Nowy folder. i utwórz nowy folder o nazwiecomponents.Jest to wspólna konwencja umieszczania składników w folderze components, ale nie jest to wymagane.
Kliknij prawym przyciskiem myszy nowy folder, wybierz pozycję Dodaj > nowy element, a następnie wybierz pozycję Plik składnika React JSX w oknie dialogowym, nadaj mu
TodoListnazwę , a następnie kliknij przycisk Dodaj. Jeśli nie widzisz listy szablonów elementów, wybierz pozycję Pokaż wszystkie szablony.
Spowoduje to utworzenie nowego pliku JSX w folderze components.
Otwórz składnik
TodoListi zastąp zawartość domyślną następującym kodem:function TodoList() { return ( <h2>TODO app contents</h2> ); } export default TodoList;Ten składnik wyświetla nagłówek, który zostanie zastąpiony później.
Następnie skonfiguruj ten składnik w aplikacji.
App.jsxjest głównym składnikiem, który jest ładowany, który reprezentuje aplikację listy to-do. Ten składnik jest używany w plikumain.jsx.W Eksploratorze rozwiązań otwórz
App.jsx, usuń wszystkie importy z góry i wyczyść zawartość instrukcji return. Plik powinien wyglądać podobnie do poniższego.function App() { return ( <> <TodoList /> </> ); } export default App;Aby dodać składnik TodoList, umieść kursor wewnątrz fragmentu, a następnie wpisz
<TodoL RETURNlub<TodoL TAB. Spowoduje to dodanie składnika. Może również automatycznie dodać instrukcję importu.
Jeśli instrukcja importu nie zostanie dodana automatycznie, dodaj ją na początku pliku, wpisując
import TodoLi naciskając TAB .Następnie wyczyść pliki CSS.
Otwórz
App.cssi usuń całą zawartość.Otwórz
Index.cssi usuń całą zawartość z wyjątkiem stylów: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; }
Uruchamianie aplikacji
Wybierz przycisk Rozpocznij debugowanie na pasku narzędzi lub naciśnij skrót klawiaturowy F5.
Aplikacja zostanie otwarta w oknie przeglądarki.
Dodawanie funkcji listy to-do do aplikacji
Możesz pozostawić uruchomioną aplikację. Podczas wprowadzania zmian aplikacja jest automatycznie odświeżana z najnowszą zawartością dzięki obsłudze hot module replacement Vite. Niektóre akcje, takie jak dodawanie folderów lub zmienianie nazw plików, wymagają zatrzymania debugowania, a następnie ponownego uruchomienia aplikacji, ale ogólnie rzecz biorąc, możesz pozostawić ją uruchomioną w tle podczas opracowywania aplikacji. Otwórz składnik TodoList.jsx, aby można było go zdefiniować.
W Eksploratorze rozwiązań otwórz
TodoList.jsxi dodaj interfejs użytkownika wymagany do wyświetlania wpisów listy to-do i zarządzania nimi. Zastąp zawartość następującym kodem: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;Powyższy kod dodaje pole wejściowe dla nowego zadania to-do i przycisk umożliwiający przesłanie danych wejściowych. Następnie podłączasz przycisk Dodaj. Użyj useState React hook, aby dodać dwie zmienne stanu, jedną dla zadania dodawanego, a drugą do przechowywania istniejących zadań. W tym samouczku zadania są przechowywane w pamięci, a nie w trwałej pamięci.
Dodaj następującą instrukcję importu do
TodoList.jsx, aby zaimportowaćuseState.import { useState } from 'react'Następnie użyj tego haka, aby utworzyć zmienne stanu. Dodaj następujący kod w funkcji
TodoListpowyżej instrukcji return.const [tasks, setTasks] = useState(["Drink some coffee", "Create a TODO app", "Drink some more coffee"]); const [newTaskText, setNewTaskText] = useState("");Spowoduje to skonfigurowanie dwóch zmiennych,
tasksinewTaskText, dla danych i dwóch funkcji, które można wywołać w celu zaktualizowania tych zmiennych,setTasksisetNewTasks. Gdy wartość zmiennej stanu zostanie zmieniona, platforma React automatycznie ponownie renderuje składnik.Jesteś prawie gotowy zaktualizować TodoList.jsx, aby pokazać to-do przedmioty jako listę, ale najpierw trzeba poznać ważną koncepcję React.
W rozwiązaniu React po wyświetleniu listy elementów należy dodać klucz w celu unikatowego zidentyfikowania każdego elementu na liście. Ta funkcja została szczegółowo wyjaśniona w dokumentacji React w sekcji Rendering Lists, ale tutaj poznasz podstawy. Masz listę elementów to-do do wyświetlenia i musisz skojarzyć unikatowy klucz dla każdego elementu. Klucz dla każdego elementu nie powinien ulec zmianie i z tego powodu nie można użyć indeksu elementu w tablicy jako klucza. Potrzebujesz identyfikatora, który nie zmieni się przez cały okres istnienia tych wartości. Użyjesz randomUID(), aby utworzyć unikatowy identyfikator dla każdego elementu to-do.
Utwórz TodoList.jsx przy użyciu identyfikatora UUID jako klucza dla każdego elementu to-do. Zaktualizuj todoList.jsx przy użyciu następującego kodu.
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;Ponieważ wartości identyfikatorów są przypisywane poza funkcją TodoList, możesz mieć pewność, że wartości nie zmienią się, jeśli strona zostanie ponownie renderowana. Podczas próby użycia aplikacji w tym stanie zauważysz, że nie można wpisywać tekstu w pole wejściowe listy zadań. Jest to spowodowane tym, że element wejściowy jest powiązany z
newTaskText, który został zainicjowany pustym ciągiem. Aby umożliwić użytkownikom dodawanie nowych zadań, musisz obsługiwać zdarzenieonChangew tej kontrolce. Należy również zaimplementować obsługę przycisku Dodaj.Dodaj wymagane funkcje bezpośrednio przed instrukcją return w funkcji 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(); }W funkcji
handleInputChangednowa wartość z pola wejściowego jest przekazywana za pośrednictwemevent.target.value, a ta wartość jest używana do aktualizowania wartości zmiennejnewTaskTextprzy użyciusetNewTaskText. W funkcjiaddTaskdodaj nowe zadanie do listy istniejących zadań przy użyciusetTasksi ustaw identyfikator elementu jako nową wartość UUID. Zaktualizuj element wejściowy, aby uwzględniłonChange={handleInputChange}i zaktualizuj przycisk Dodaj, aby uwzględnićonClick={addTask}. Ten kod podłącza zdarzenie do funkcji obsługującej to zdarzenie. Po tym powinieneś móc dodać nowe zadanie do listy zadań. Nowe zadania są dodawane do dołu listy. Aby zwiększyć użyteczność tej aplikacji, należy dodać obsługę usuwania zadań i przenieść zadanie w górę lub w dół.Dodaj funkcje do obsługi usuwania, przenoszenia w górę i przenoszenia w dół, a następnie zaktualizuj znaczniki, aby wyświetlić przycisk odpowiadający każdej z tych akcji. Dodaj następujący kod w funkcji TodoList powyżej instrukcji return.
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); } }Funkcja delete przyjmuje identyfikator zadania i usuwa tę z listy i używa metody Array filter(), aby utworzyć nową tablicę z wyłączeniem wybranego elementu, a następnie wywołuje
setTasks(). Pozostałe dwie funkcje przyjmują indeks elementu, ponieważ działanie to jest specyficzne dla kolejności elementów. ZarównomoveTaskUp(), jak imoveTaskDown()używają destruktowania przypisania, aby zamienić wybrane zadanie z jego sąsiadem.Następnie zaktualizuj widok, aby uwzględnić te trzy przyciski. Zaktualizuj instrukcję return, aby zawierała następujące elementy.
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> );Dodano przyciski potrzebne do wykonania wcześniej omówionych zadań. Używasz znaków Unicode jako ikon na przyciskach. W znaczniku dodano niektóre atrybuty, aby umożliwić późniejsze dodanie niektórych arkuszy CSS. Możesz również zauważyć użycie atrybutów aria , aby poprawić dostępność; są one opcjonalne, ale zdecydowanie zalecane. Jeśli uruchomisz aplikację, powinna ona wyglądać podobnie do poniższej ilustracji.
Teraz powinno być możliwe wykonanie następujących czynności w aplikacji internetowej TODO.
- Dodaj zadanie
- Usuń zadanie
- Przenieś zadanie w górę
- Przenieś zadanie w dół
Te funkcje działają, ale możesz zrefaktoryzować kod, aby zbudować składnik wielokrotnego użycia do wyświetlania elementów to-do. Znacznik dla elementu to-do trafia do nowego komponentu TodoItem. Ponieważ zarządzanie listą pozostaje w składniku Todo, można przekazać wywołania zwrotne do przycisków Usuń i Przenieś.
Aby rozpocząć, naciśnij prawym przyciskiem myszy folder składników w Eksploratorze rozwiązań i wybierz Dodaj > Nowy Element.
W wyświetlonym oknie dialogowym wybierz plik komponentu React JSX, nazwij go TodoItem, a następnie kliknij Dodaj.
Dodaj następujący kod do elementu TodoItem.
W tym kodzie przekazujesz zadanie i wywołania zwrotne jako właściwości tego nowego składnika.
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;Powyższy kod zawiera kod znaczników składnika Todo, a na końcu którego deklarujesz
PropTypes. Props są używane do przekazywania danych z komponentu nadrzędnego do komponentów podrzędnych. Aby uzyskać więcej informacji na temat props, zobacz Przekazywanie props do składnika — React. Ponieważ funkcje usuwania i przenoszenia są przekazywane jako wywołania zwrotne, program obsługionClickmusi zostać zaktualizowany w celu wywołania tych wywołań zwrotnych.Dodaj wymagany kod. Pełny kod todoList, który używa składnika TodoItem, jest pokazany tutaj.
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;Teraz składnik TodoItem jest używany do renderowania każdego elementu to-do. Zwróć uwagę, że klucz jest ustawiony na wartość
task.id, która zawiera wartość UUID dla tego zadania. Po uruchomieniu aplikacji nie powinno być widocznych żadnych zmian w wyglądzie ani zachowaniu aplikacji, ponieważ została zrefaktoryzowana do korzystania z TodoItem.Teraz, gdy wszystkie podstawowe funkcje są już obsługiwane, nadszedł czas, aby dodać trochę stylizacji, aby wyglądało to atrakcyjnie. Zacznij od dodania linku w Index.html dla rodziny czcionek Inter, który będzie używany dla tej aplikacji. W Index.htmlistnieją inne elementy, które należy wyczyścić. W szczególności tytuł powinien zostać zaktualizowany i chcesz zastąpić plik vite.svg, który jest obecnie używany jako ikona.
Zaktualizuj Index.html przy użyciu następującej zawartości.
<!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>Edytuj plik main.jsx, aby podczas wywoływania
rootzastąpićmaincreateRoot.Pełny kod dla main.jsx jest pokazany tutaj.
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>, )Oprócz tych zmian plik checkmark-square.svg został dodany do folderu publicznego. Jest to plik SVG z obrazu kwadratu znacznika wyboru FluentUI, który można pobrać bezpośrednio. (Istnieje pakiet, którego można użyć do bardziej zintegrowanego środowiska, ale wykracza poza zakres tego artykułu).
Następnie zaktualizuj style składnika TodoList.
W folderze components dodaj nowy plik CSS o nazwie TodoList.css. Możesz kliknąć prawym przyciskiem myszy projekt i wybrać pozycję Dodaj > Nowy Element, a następnie wybrać arkusz stylów. Nadaj plikowi nazwę TodoList.css.
Dodaj następujący kod do TodoList.css.
.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; }Następnie zmodyfikuj TodoList.jsx, aby dodać następujący import w górnej części pliku.
import './TodoList.css';Odśwież przeglądarkę po zapisaniu zmian. Powinno to poprawić styl aplikacji. Aplikacja powinna wyglądać podobnie do poniższej.
Teraz utworzono działającą aplikację listy to-do, która przechowuje elementy to-do w pamięci. Od tego momentu możesz zaktualizować aplikację, aby przechowywać elementy to-do w localStorage/IndexedDb, lub zintegrować ją z bazą danych po stronie serwera albo innym zapleczem dla bardziej trwałego przechowywania.
Streszczenie
W tym samouczku utworzyłeś nową aplikację React przy użyciu programu Visual Studio. Aplikacja składa się z listy to-do, która obejmuje obsługę dodawania zadań, usuwania zadań i zmieniania ich kolejności. Stworzyłeś dwa nowe komponenty React i używałeś ich przez cały ten samouczek.
Zasoby
- Kod dla tego przykładu w ToDoJSWebApp
- Projekty Visual Studio JavaScript i TypeScript