Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Dalam tutorial ini, Anda membuat front-end React untuk aplikasi web daftar to-do menggunakan JavaScript dan Visual Studio 2022. Kode untuk aplikasi ini dapat ditemukan di ToDoJSWebApp.
Prasyarat
Pastikan untuk menginstal hal berikut:
- Visual Studio 2022 atau yang lebih baru. Buka halaman unduhan Visual Studio untuk menginstalnya secara gratis.
- npm (
https://www.npmjs.com/), yang disertakan dengan Node.js.
Buat aplikasi React Daftar Tugas
Di Visual Studio, pilih File > Proyek Baru > untuk membuka dialog Buat Proyek Baru, pilih templat React App JavaScript, lalu pilih Berikutnya.
Beri nama
TodoWebAppproyek dan pilih Buat.Proyek JavaScript ini dibuat menggunakan perangkat baris perintah vite.
Di Penjelajah Solusi, klik kanan folder
srcdan pilih Tambahkan > Folder Baru. dan buat folder baru bernamacomponents.Ini adalah konvensi umum untuk menempatkan komponen dalam folder komponen, tetapi ini tidak diperlukan.
Klik kanan folder baru, pilih Tambahkan > Item Baru, lalu pilih File Komponen React JSX dalam kotak dialog, beri nama
TodoList, dan klik Tambahkan. Jika Anda tidak melihat daftar templat item, pilih Perlihatkan Semua Templat.
Ini membuat file JSX baru di folder komponen.
Buka komponen
TodoListdan ganti konten default dengan yang berikut ini:function TodoList() { return ( <h2>TODO app contents</h2> ); } export default TodoList;Komponen ini menampilkan header, yang akan Anda ganti nanti.
Selanjutnya, hubungkan komponen ini dalam aplikasi.
App.jsxadalah komponen utama yang dimuatkan, yang mewakili daftar aplikasi to-do. Komponen ini digunakan dalam filemain.jsx.Di Penjelajah Solusi, buka
App.jsx, hapus semua impor dari bagian atas, dan hapus konten pernyataan pengembalian. File akan terlihat seperti berikut ini.function App() { return ( <> <TodoList /> </> ); } export default App;Untuk menambahkan komponen TodoList, letakkan kursor Anda di dalam fragmen lalu ketik
<TodoL RETURNatau<TodoL TAB. Ini menambahkan komponen. Ini mungkin juga secara otomatis menambahkan pernyataan impor.
Jika pernyataan impor tidak ditambahkan secara otomatis, tambahkan di awal file dengan mengetik
import TodoLdan menekan tombol TAB .Selanjutnya, hapus file CSS.
Buka
App.cssdan hapus semua konten.Buka
Index.cssdan hapus semua konten kecuali gaya untuk: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; }
Menjalankan aplikasi
Pilih tombol Mulai Penelusuran Kesalahan dari toolbar atau tekan pintasan keyboard F5.
Aplikasi terbuka di jendela browser.
Menambahkan fungsi daftar to-do ke aplikasi
Anda dapat membiarkan aplikasi berjalan. Saat Anda membuat perubahan, aplikasi secara otomatis memperbarui dengan konten terbaru menggunakan dukungan penggantian modul cepat Vite. Beberapa tindakan, seperti menambahkan folder atau mengganti nama file, mengharuskan Anda menghentikan penelusuran kesalahan lalu memulai ulang aplikasi, tetapi secara umum Anda dapat membiarkannya berjalan di latar belakang saat mengembangkan aplikasi Anda. Buka komponen TodoList.jsx sehingga kita dapat mulai menentukannya.
Di Penjelajah Solusi, buka
TodoList.jsxdan tambahkan UI yang diperlukan untuk menampilkan dan mengelola entri daftar to-do. Ganti konten dengan kode berikut: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;Kode sebelumnya menambahkan kotak input untuk tugas to-do baru dan tombol untuk mengirimkan input. Selanjutnya, Anda menyambungkan tombol Tambahkan. Gunakan kait useState React untuk menambahkan dua variabel status, satu untuk tugas yang ditambahkan, dan satu lagi untuk menyimpan tugas yang ada. Untuk tutorial ini, tugas disimpan dalam memori dan bukan penyimpanan persisten.
Tambahkan pernyataan impor berikut ke
TodoList.jsxuntuk mengimporuseState.import { useState } from 'react'Selanjutnya, gunakan hook tersebut untuk membuat variabel status. Tambahkan kode berikut dalam fungsi
TodoListdi atas pernyataan pengembalian.const [tasks, setTasks] = useState(["Drink some coffee", "Create a TODO app", "Drink some more coffee"]); const [newTaskText, setNewTaskText] = useState("");Ini menyiapkan dua variabel,
tasksdannewTaskText, untuk data dan dua fungsi yang dapat Anda panggil untuk memperbarui variabel tersebut,setTasksdansetNewTasks. Saat nilai untuk variabel status diubah, React secara otomatis merender ulang komponen.Anda hampir siap untuk memperbarui TodoList.jsx untuk menampilkan item to-do sebagai daftar, tetapi ada konsep React penting untuk dipelajari terlebih dahulu.
Di React, saat Anda menampilkan daftar item, Anda perlu menambahkan kunci untuk mengidentifikasi setiap item secara unik dalam daftar. Fitur ini dijelaskan secara mendalam dalam dokumentasi React di Rendering Daftar, tetapi di sini Anda akan mempelajari dasar-dasarnya. Anda memiliki daftar item to-do untuk ditampilkan, dan Anda perlu mengaitkan kunci unik untuk setiap item. Kunci untuk setiap item tidak boleh berubah, dan karena alasan ini Anda tidak dapat menggunakan indeks item dalam array sebagai kunci. Anda memerlukan ID yang tidak akan berubah sepanjang masa pakai nilai tersebut. Anda akan menggunakan randomUUID() untuk membuat ID unik untuk setiap item to-do.
Buat todoList.jsx menggunakan UUID sebagai kunci untuk setiap item to-do. Perbarui todoList.jsx dengan kode berikut.
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;Karena nilai ID ditetapkan di luar fungsi TodoList, Anda dapat yakin nilai tidak akan berubah jika halaman dirender ulang. Saat mencoba aplikasi dalam status ini, Anda akan melihat bahwa Anda tidak dapat mengetikkan elemen input todo. Ini karena elemen input terikat ke
newTaskText, yang telah diinisialisasi ke string kosong. Untuk mengizinkan pengguna menambahkan tugas baru, Anda perlu menangani peristiwaonChangepada kontrol tersebut. Anda juga perlu menerapkan dukungan tombol Tambahkan.Tambahkan fungsi yang diperlukan segera sebelum pernyataan pengembalian dalam fungsi 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(); }Dalam fungsi
handleInputChanged, nilai baru dari bidang input diteruskan melaluievent.target.value, dan nilai tersebut digunakan untuk memperbarui nilai untuk variabelnewTaskTextdengansetNewTaskText. Dalam fungsiaddTask, tambahkan tugas baru ke daftar tugas yang ada menggunakansetTasksdan atur ID item sebagai nilai UUID baru. Perbarui elemen input untuk menyertakanonChange={handleInputChange}dan perbarui tombol Tambahkan untuk menyertakanonClick={addTask}. Kode ini menghubungkan peristiwa ke fungsi yang menangani peristiwa tersebut. Setelah ini, Anda akan dapat menambahkan tugas baru ke daftar tugas. Tugas baru ditambahkan ke bagian bawah daftar. Agar aplikasi ini lebih berguna, Anda perlu menambahkan dukungan untuk menghapus tugas dan memindahkan tugas ke atas atau ke bawah.Tambahkan fungsi untuk mendukung penghapusan, pindah ke atas dan pindah ke bawah, lalu perbarui markup untuk menampilkan tombol untuk setiap tindakan. Tambahkan kode berikut dalam fungsi TodoList di atas pernyataan pengembalian.
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); } }Fungsi penghapusan menerima ID tugas, lalu menghapusnya dari daftar, dan menggunakan metode filter Array untuk membuat array baru yang tidak termasuk item yang dipilih, kemudian memanggil
setTasks(). Dua fungsi lainnya mengambil indeks item karena pekerjaan ini khusus untuk pengurutan item. BaikmoveTaskUp()maupunmoveTaskDown()menggunakan penugasan penghancuran array untuk menukar tugas yang dipilih dengan tetangganya.Selanjutnya, perbarui tampilan untuk menyertakan tiga tombol ini. Perbarui pernyataan pengembalian untuk berisi yang berikut ini.
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> );Anda telah menambahkan tombol yang diperlukan untuk melakukan tugas yang kami bahas sebelumnya. Anda menggunakan karakter Unicode sebagai ikon pada tombol. Dalam markup, ada beberapa atribut yang ditambahkan untuk mendukung penambahan beberapa CSS nanti. Anda mungkin juga memperhatikan penggunaan atribut aria untuk meningkatkan aksesibilitas, yang opsional namun sangat dianjurkan. Jika Anda menjalankan aplikasi, aplikasi akan terlihat seperti ilustrasi berikut.
Anda sekarang dapat melakukan hal berikut di aplikasi web TODO.
- Menambahkan tugas
- Hapus tugas
- Pindahkan tugas ke atas
- Pindahkan tugas ke bawah
Fungsi-fungsi ini berfungsi, tetapi Anda dapat merefaktor untuk membangun komponen yang dapat digunakan kembali untuk menampilkan item to-do. Markup untuk item to-do masuk ke komponen baru, TodoItem. Karena manajemen daftar tetap berada di komponen Todo, Anda dapat meneruskan panggilan balik ke tombol Hapus dan Pindahkan.
Untuk memulai, klik kanan folder komponen di Penjelajah Solusi dan pilih Tambahkan > Item Baru.
Dalam dialog yang terbuka, pilih File Komponen React JSX, beri nama TodoItem, dan pilih Tambahkan.
Tambahkan kode berikut ke TodoItem.
Dalam kode ini, Anda meneruskan tugas dan panggilan balik sebagai properti ke komponen baru ini.
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;Kode sebelumnya berisi markup dari komponen Todo dan di akhir kode tersebut Anda mendeklarasikan
PropTypes. Alat peraga digunakan untuk meneruskan data dari komponen induk ke komponen turunan. Untuk informasi selengkapnya tentang Props, lihat Meneruskan Props ke Komponen – React. Karena fungsi hapus dan pindahkan sedang diteruskan sebagai panggilan balik, handleronClickperlu diperbarui untuk memanggil panggilan balik tersebut.Tambahkan kode yang diperlukan. Kode lengkap untuk TodoList yang menggunakan komponen TodoItem ditampilkan di sini.
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;Sekarang, komponen TodoItem digunakan untuk merender setiap item to-do. Perhatikan bahwa kunci diatur ke
task.id, yang berisi nilai UUID untuk tugas tersebut. Saat menjalankan aplikasi, Anda seharusnya tidak melihat perubahan apa pun pada tampilan atau perilaku aplikasi karena Anda merefaktornya untuk menggunakan TodoItem.Sekarang setelah Anda memiliki semua fungsi dasar yang didukung, saatnya untuk mulai menambahkan beberapa gaya ke ini untuk membuatnya terlihat bagus. Mulailah dengan menambahkan tautan di Index.html untuk keluarga font, Inter, yang akan Anda gunakan untuk aplikasi ini. Dalam Index.html, ada beberapa item lain yang perlu dibersihkan. Secara khusus, judul harus diperbarui dan Anda ingin mengganti file vite.svg yang saat ini digunakan sebagai ikon.
Perbarui Index.html dengan konten berikut.
<!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>Edit file main.jsx untuk mengganti
rootdenganmainsaat memanggilcreateRoot.Kode lengkap untuk main.jsx ditampilkan di sini.
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>, )Selain perubahan ini, file checkmark-square.svg ditambahkan ke folder publik. Ini adalah SVG dari gambar persegi tanda centang FluentUI, yang dapat Anda unduh secara langsung. (Ada paket yang dapat Anda gunakan untuk pengalaman yang lebih terintegrasi, tetapi itu di luar cakupan artikel ini.)
Selanjutnya, perbarui gaya komponen TodoList.
Di folder komponen, tambahkan file CSS baru bernama TodoList.css. Anda dapat mengklik kanan proyek dan memilih > Item Baru lalu pilih Lembar Gaya . Beri nama file TodoList.css.
Tambahkan kode berikut ke 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; }Selanjutnya, edit todoList.jsx untuk menambahkan impor berikut di bagian atas file.
import './TodoList.css';Refresh browser setelah menyimpan perubahan. Ini seharusnya meningkatkan tampilan aplikasi. Aplikasi akan terlihat seperti berikut ini.
Sekarang Anda telah membuat aplikasi daftar to-do yang berfungsi yang menyimpan item to-do dalam memori. Dari titik ini, Anda dapat memperbarui aplikasi untuk menyimpan item to-do di localStorage/IndexedDb, atau mengintegrasikannya dengan database sisi server, atau backend lainnya, untuk penyimpanan yang lebih permanen.
Ringkasan
Dalam tutorial ini, Anda membuat aplikasi React baru menggunakan Visual Studio. Aplikasi ini terdiri dari daftar to-do, yang mencakup dukungan untuk menambahkan tugas, menghapus tugas, dan menyusun ulang. Anda membuat dua komponen React baru dan menggunakannya di seluruh tutorial ini.
Sumber daya
- Kode untuk sampel ini di ToDoJSWebApp
- proyek Visual Studio JavaScript dan TypeScript