Chào mừng các bạn đến với bài thực hành nhập môn lập trình web! Hôm nay, chúng ta sẽ cùng nhau xây dựng một ứng dụng Todo List (Danh sách việc cần làm). Đây là dự án kinh điển giúp bạn hiểu rõ cách HTML, CSS và JavaScript phối hợp để tạo ra một trang web có tính tương tác.
Chúng ta sẽ đi qua 3 bước chính:
Dưới đây là cấu trúc HTML:
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Todo List</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<h2>Danh Sách Việc Cần Làm</h2>
<div class="input-group">
<input
type="text"
id="todo-input"
placeholder="Nhập công việc mới..."
/>
<button id="add-btn">Thêm</button>
</div>
<ul id="todo-list"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
Giải thích mã:
div.container: Thẻ bao bọc toàn bộ
nội dung chính để dễ căn chỉnh giữa màn hình.
input: Có
id="todo-input" để JavaScript có
thể lấy được nội dung người dùng nhập.
button: Có
id="add-btn" để JavaScript bắt sự
kiện khi người dùng click vào.
ul: Có
id="todo-list". Đây là một danh
sách không thứ tự rỗng, nơi chúng ta sẽ chèn các thẻ
<li> (các công việc) vào sau này.
Nếu chỉ có HTML, trang web trông sẽ rất đơn điệu. Chúng ta sẽ dùng CSS để căn giữa giao diện, tạo khoảng cách và màu sắc dễ nhìn hơn.
Hãy thêm đoạn mã sau vào file
style.css:
/* Cấu hình chung cho trang */
body {
font-family: 'Arial', sans-serif;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
height: 100vh; /* Chiều cao bằng 100% màn hình */
margin: 0;
}
/* Khung chứa chính */
.container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
width: 350px;
}
h2 {
text-align: center;
color: #333;
}
/* Khu vực nhập liệu */
.input-group {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
input {
flex-grow: 1; /* Input chiếm hết khoảng trống còn lại */
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
button#add-btn {
padding: 10px 15px;
background-color: #28a745;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button#add-btn:hover {
background-color: #218838;
}
/* Danh sách công việc */
ul {
list-style-type: none; /* Bỏ dấu chấm tròn mặc định */
padding: 0;
}
li {
background: #fff;
border-bottom: 1px solid #eee;
padding: 10px;
display: flex;
justify-content: space-between; /* Đẩy nội dung và nút xóa sang 2 bên */
align-items: center;
}
/* Nút xóa */
.delete-btn {
background-color: #dc3545;
color: white;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
Giải thích mã:
display: flex): Được
sử dụng rất nhiều để căn giữa nội dung
body và sắp xếp các phần tử
li (nội dung bên trái, nút xóa bên
phải).
list-style-type: none: Loại bỏ các
dấu chấm đầu dòng mặc định của thẻ
<ul> để danh sách trông gọn
gàng hơn.
Đây là phần quan trọng nhất. Chúng ta cần viết mã JavaScript để thực hiện quy trình sau:
<li> mới chứa
nội dung đó và một nút Xóa.
<li> này vào
<ul>.
<li> tương ứng.
Dưới đây là mã cho file script.js:
// 1. Chọn các phần tử cần thiết từ DOM
const input = document.getElementById('todo-input');
const addBtn = document.getElementById('add-btn');
const todoList = document.getElementById('todo-list');
// 2. Hàm thêm công việc mới
function addTodo() {
// Lấy giá trị người dùng nhập và loại bỏ khoảng trắng thừa
const taskText = input.value.trim();
// Kiểm tra nếu ô nhập rỗng thì không làm gì cả
if (taskText === '') {
alert("Vui lòng nhập nội dung công việc!");
return;
}
// Tạo thẻ li mới
const li = document.createElement('li');
// Tạo nội dung text cho li
const span = document.createElement('span');
span.textContent = taskText;
// Tạo nút xóa
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Xóa';
deleteBtn.classList.add('delete-btn'); // Thêm class để nhận CSS
// Gắn sự kiện xóa cho nút vừa tạo
deleteBtn.onclick = function() {
todoList.removeChild(li);
};
// Gắn text và nút xóa vào thẻ li
li.appendChild(span);
li.appendChild(deleteBtn);
// Gắn thẻ li vào danh sách ul
todoList.appendChild(li);
// Xóa nội dung trong ô input sau khi thêm xong
input.value = '';
input.focus(); // Đặt trỏ chuột lại vào ô input
}
// 3. Lắng nghe sự kiện click vào nút "Thêm"
addBtn.addEventListener('click', addTodo);
// Nâng cao: Cho phép ấn Enter để thêm
input.addEventListener('keypress', function(event) {
if (event.key === 'Enter') {
addTodo();
}
});
Giải thích mã:
document.getElementById: Giúp JS
"túm" lấy các thẻ HTML để thao tác.
document.createElement: Tạo ra các
thẻ HTML mới hoàn toàn từ bộ nhớ (chưa hiện lên màn hình).
appendChild: Đây là lệnh đưa phần tử
con vào trong phần tử cha. Ví dụ: Đưa nút Xóa vào trong dòng công việc
(li), rồi đưa dòng công việc vào
danh sách (ul).
onclick ngay
lúc tạo nút đó. Khi click, nó sẽ tìm đến cha của nó (thẻ
li) và yêu cầu
todoList gỡ bỏ đứa con này (removeChild).