Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I den här handledningen skapar du en React-front-end för en to-do-lista med hjälp av JavaScript och Visual Studio 2022. Koden för den här appen finns på ToDoJSWebApp.
Förutsättningar
Se till att installera följande:
- Visual Studio 2022 eller senare. Gå till Visual Studio nedladdningar-sidan och installera den kostnadsfritt.
- npm (https://www.npmjs.com/), som ingår i Node.js.
Skapa React ToDo List-appen
- I Visual Studio väljer du File > New > Project för att öppna dialogrutan Skapa ett nytt projekt, välj mallen React App JavaScript och välj sedan Nästa.   
- Ge projektet namnet - TodoWebAppoch välj Skapa.- Då skapas JavaScript-projektet med kommandoradsverktyget vite. 
- Högerklicka på mappen - srci Solution Explorer och välj Lägg till > ny mapp. och skapa en ny mapp med namnet- components.- Det är en vanlig konvention att placera komponenter i en komponentmapp, men det krävs inte. 
- Högerklicka på den nya mappen, välj Lägg till > nytt objekt, välj sedan React JSX-komponentfil i dialogrutan, ge den - TodoListnamnet och klicka på Lägg till. Om du inte ser en lista med objektmallar väljer du Visa alla mallar.  - Då skapas en ny JSX-fil i komponentmappen. 
- Öppna komponenten - TodoListoch ersätt standardinnehållet med följande:- function TodoList() { return ( <h2>TODO app contents</h2> ); } export default TodoList;- Den här komponenten visar en rubrik som du kommer att ersätta senare. - Anslut sedan den här komponenten i appen. - App.jsxär huvudkomponenten som läses in, som representerar to-do listapplikationen. Den här komponenten används i filen- main.jsx.
- I Solution Explorer öppnar du - App.jsx, tar bort alla importer överst och rensar ut innehållet i returutdraget. Filen bör se ut så här.- function App() { return ( <> <TodoList /> </> ); } export default App;
- Om du vill lägga till TodoList-komponenten placerar du markören i fragmentet och skriver - <TodoL RETURNeller- <TodoL TAB. Detta lägger till komponenten. Det kan också automatiskt lägga till import-instruktionen.  - Om importinstruktionen inte läggs till automatiskt lägger du till den i början av filen genom att - import TodoLskriva och trycka på TAB-tangenten .- Rensa sedan CSS-filerna. 
- Öppna - App.cssoch ta bort allt innehåll.
- Öppna - Index.cssoch ta bort allt innehåll förutom formatmallarna för- :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; }
Kör appen
Välj knappen Starta felsökning i verktygsfältet eller tryck på kortkommandot F5.
Appen öppnas i ett webbläsarfönster.
              
               
              
              
            
Lägg till to-do listfunktioner i appen
Du kan låta appen köras. När du gör ändringar uppdateras appen automatiskt med det senaste innehållet med hjälp av Vites stöd för ersättning av frekventa moduler. Vissa åtgärder, till exempel att lägga till mappar eller byta namn på filer, kräver att du slutar felsöka och sedan startar om appen, men i allmänhet kan du låta den köras i bakgrunden när du utvecklar appen. Öppna komponenten TodoList.jsx så att vi kan börja definiera den.
- I Solution Explorer öppnar du - TodoList.jsxoch lägger till det användargränssnitt som behövs för att visa och hantera to-do listposter. Ersätt innehållet med följande kod:- 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;- Föregående kod lägger till en indataruta för den nya to-do uppgiften och en knapp för att skicka indata. Sedan kopplar du upp knappen Lägg till. Använd useState React-kroken för att lägga till två tillståndsvariabler, en för uppgiften som läggs till och en annan för att lagra befintliga uppgifter. I den här handledningen lagras uppgifterna i minnet och inte i permanent lagring. 
- Lägg till följande importuttryck i - TodoList.jsxför att importera- useState.- import { useState } from 'react'
- Använd sedan den kroken för att skapa tillståndsvariablerna. Lägg till följande kodsnutt i - TodoList-funktionen ovanför retursatsen.- const [tasks, setTasks] = useState(["Drink some coffee", "Create a TODO app", "Drink some more coffee"]); const [newTaskText, setNewTaskText] = useState("");- Detta konfigurerar två variabler, - tasksoch- newTaskText, för data och två funktioner som du kan anropa för att uppdatera variablerna,- setTasksoch- setNewTasks. När ett värde för en tillståndsvariabel ändras återger React komponenten automatiskt igen.- Du är nästan redo att uppdatera TodoList.jsx för att visa to-do objekt som en lista, men det finns ett viktigt React-koncept att lära dig först. - När du visar en lista med objekt i React måste du lägga till en nyckel för att unikt identifiera varje objekt i listan. Den här funktionen beskrivs ingående i React-dokumenten på Renderingslistor, men här lär du dig grunderna. Du har en lista över to-do objekt som ska visas och du måste associera en unik nyckel för varje objekt. Nyckeln för varje objekt bör inte ändras och därför kan du inte använda objektets index i matrisen som nyckel. Du behöver ett ID som inte ändras under dessa värdens livslängd. Du använder randomUUID() för att skapa ett unikt ID för varje to-do objekt. 
- Skapa TodoList.jsx med en UUID som nyckel för varje to-do objekt. Uppdatera TodoList.jsx- med följande kod. - 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;- Eftersom ID-värdena tilldelas utanför funktionen TodoList kan du vara säker på att värdena inte ändras om sidan återges på nytt. När du provar appen i det här tillståndet ser du att du inte kan skriva in i todo-indataelementet. Det beror på att indataelementet är bundet till - newTaskText, som har initierats till en tom sträng. Om du vill tillåta användare att lägga till nya uppgifter måste du hantera- onChange-händelsen på den kontrollen. Du måste också implementera stöd för knappen Lägg till.
- Lägg till funktionerna som behövs omedelbart före retursatsen i funktionen 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(); }- I funktionen - handleInputChangedskickas det nya värdet från indatafältet via- event.target.valueoch det värdet används för att uppdatera värdet för variabeln- newTaskTextmed- setNewTaskText. I funktionen- addTasklägger du till den nya aktiviteten i listan över befintliga aktiviteter med hjälp av- setTasksoch anger objektets ID som ett nytt UUID-värde. Uppdatera indataelementet så att det innehåller- onChange={handleInputChange}och uppdatera knappen Lägg till för att inkludera- onClick={addTask}. Den här koden kopplar händelsen till den funktion som hanterar händelsen. Efter detta bör du kunna lägga till en ny uppgift i uppgiftslistan. Nya uppgifter läggs till längst ned i listan. För att göra den här appen mer användbar måste du lägga till stöd för att ta bort uppgifter och flytta en aktivitet uppåt eller nedåt.
- Lägg till funktionerna för att stödja borttagning, flytta upp och flytta nedåt och uppdatera sedan markering för att visa en knapp för varje åtgärd. Lägg till följande kod i funktionen TodoList ovanför retursatsen. - 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); } }- Borttagningsfunktionen tar in aktivitets-ID:t och tar bort det från listan och använder metoden Array filter() för att skapa en ny matris exklusive det markerade objektet och anropar sedan - setTasks(). De andra två funktionerna tar in objektets index eftersom det här arbetet är specifikt för objektordningen. Både- moveTaskUp()och- moveTaskDown()använder tilldelning med matrisdestrukturering för att växla den valda uppgiften med grannen.
- Uppdatera sedan vyn så att den innehåller de här tre knapparna. Uppdatera retursatsen så att den innehåller följande. - 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> );- Du har lagt till knapparna som behövs för att utföra de uppgifter som vi diskuterade tidigare. Du använder Unicode-tecken som ikoner på knapparna. I markupen finns det några attribut som har lagts till som stöd för att lägga till CSS-stilar senare. Du kanske också märker användningen av aria-attribut för att förbättra tillgängligheten, vilket är valfritt men rekommenderas starkt. Om du kör appen bör den se ut som följande bild.   - Du bör nu kunna utföra följande i TODO-webbappen. - Lägg till aktivitet
- Ta bort uppgift
- Flytta upp uppgiften
- Flytta aktiviteten nedåt
 - Dessa funktioner fungerar, men du kan omstrukturera för att skapa en återanvändbar komponent för att visa to-do objekt. Markup för objektet to-do placeras i den nya komponenten TodoItem. Eftersom hanteringen av listan finns kvar i Todo-komponenten kan du skicka återanrop till knapparna Ta bort och Flytta. 
- Kom igång genom att högerklicka på mappen komponenter i Solution Explorer och välja Lägg till > nytt objekt. 
- I dialogrutan som öppnas väljer du React JSX-komponentfilen, ger den namnet TodoItem och väljer Lägg till. 
- Lägg till följande kod i TodoItem. - I den här koden skickar du uppgiften och återanrop som egenskaper till den nya komponenten. - 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;- Föregående kod innehåller markering från Todo-komponenten och i slutet av den deklarerar du - PropTypes. Props används för att skicka data från en föräldrakomponent till barnkomponenter. Mer information om rekvisita finns i Skicka rekvisita till en komponent – React. Eftersom funktionerna för att ta bort och flytta skickas som återanrop måste- onClick-hanteraren uppdateras för att anropa dessa återanrop.
- Lägg till den kod som krävs. Den fullständiga koden för TodoList som använder TodoItem-komponenten visas här. - 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;- Nu används TodoItem-komponenten för att återge varje to-do objekt. Observera att nyckeln är inställd på - task.id, som innehåller UUID-värdet för aktiviteten. När du kör appen bör du inte se några ändringar i appens utseende eller beteende eftersom du omstrukturerade den för att använda TodoItem.- Nu när du har alla grundläggande funktioner som stöds är det dags att börja lägga till lite stil för att få det att se snyggt ut. Börja med att lägga till en länk i Index.html för en teckensnittsfamilj, Inter, som du ska använda för den här appen. I Index.htmlfinns det några andra objekt som måste rensas. Mer specifikt bör rubriken uppdateras och du vill ersätta den vite.svg fil som för närvarande används som ikon. 
- Uppdatera Index.html med följande innehåll. - <!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>
- Redigera main.jsx--fil för att ersätta - rootmed- mainnär du anropar- createRoot.- Den fullständiga koden för main.jsx- visas här. - 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>, )- Förutom dessa ändringar lades filen checkmark-square.svg till i den gemensamma mappen. Det här är en SVG från fluentui-bockmarkeringens kvadratbild, som du kan ladda ned direkt. (Det finns ett paket som du kan använda för en mer integrerad upplevelse, men som inte omfattas av den här artikeln.) - Uppdatera sedan formatmallarna för TodoList-komponenten. 
- I komponentmappen lägger du till en ny CSS-fil med namnet TodoList.css. Du kan högerklicka på projektet och välja Lägg till > nytt objekt och sedan välja formatmall. Ge filen namnet TodoList.css. 
- Lägg till följande kod i 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; }
- Redigera sedan TodoList.jsx- för att lägga till följande import överst i filen. - import './TodoList.css';
- Uppdatera webbläsaren när du har sparat ändringarna. Detta bör förbättra appens utseende. Appen bör se ut så här.   - Nu har du skapat en fungerande to-do listapp som lagrar de to-do objekten i minnet. Från och med nu kan du uppdatera appen för att lagra de to-do objekten i localStorage/IndexedDbeller integrera den med en databas på serversidan eller annan serverdel för mer permanent lagring. 
Sammanfattning
I den här självstudien skapade du en ny React-app med Visual Studio. Appen består av en to-do lista, som innehåller stöd för att lägga till uppgifter, ta bort uppgifter och ordna om dem. Du har skapat två nya React-komponenter och använt dem i den här självstudien.
Resurser
- Kod för det här exemplet på ToDoJSWebApp
- Visual Studio JavaScript- och TypeScript-projekt