Học Web

Khóa Học Lập Trình Web

Từ HTML, CSS, JavaScript, ES6 đến localStorage & Deployment - 7 buổi học từ A đến Z

Dành cho học sinh lớp 10 - Không cần kinh nghiệm trước đó

📚 Tổng Quan Khóa Học

Buổi 1: HTML

Dựng khung xương website - HTML cơ bản

⏱️ 75 phút | 📝 Thực hành
Buổi 2: CSS

Trang trí & CSS Box Model

⏱️ 75 phút | 📝 Thực hành
Buổi 3: Layout

Flexbox, Grid & Responsive Design

⏱️ 75 phút | 📝 Thực hành
Buổi 4: JavaScript

DOM & Tương tác người dùng

⏱️ 75 phút | 📝 Thực hành
Buổi 5: Deploy

GitHub Pages & Đưa lên Internet

⏱️ 75 phút | 📝 Thực hành + Vấn đáp
Buổi 6: localStorage

Quản lý dữ liệu & lưu trữ cục bộ

⏱️ 75 phút | 📝 Thực hành
Buổi 7: ES6 Modern

ES6 Modules, Destructuring & Spread

⏱️ 75 phút | 📝 Thực hành

Buổi 1: Dựng Khung Xương Website (HTML)

🎯 Mục Tiêu Buổi 1
  • Tư duy: Website = Ngôi nhà, HTML = Viên gạch
  • Kỹ năng: Viết thẻ HTML cơ bản
  • Sản phẩm: File index.html hoàn chỉnh
🛠️ Công Cụ Cần Dùng
  • VS Code (hoặc Editor khác)
  • Extension Live Server
  • Trình duyệt Chrome/Firefox
LÝ THUYẾT CỐT LÕI (15 Phút)
1️⃣ Bản Chất Thẻ HTML - Nguyên Tắc "Bánh Kẹp"
HTML hoạt động đơn giản: <tên_thẻ> Nội dung ở giữa </tên_thẻ>
2️⃣ Các Thẻ Chính Cần Dùng Hôm Nay:
Thẻ Tên gọi Ví dụ
<h1> đến <h6> Heading (Tiêu đề) <h1>Tựa Đề Lớn</h1>
<p> Paragraph (Đoạn văn) <p>Đoạn văn bản...</p>
<img> Image (Hình ảnh) <img src="anh.jpg" alt="Ảnh">
<a> Anchor (Liên kết) <a href="link">Click</a>
<button> Button (Nút bấm) <button>Bấm tôi</button>
3️⃣ Cấu Trúc HTML5 Cơ Bản:
HTML Skeleton
<!DOCTYPE html>
<html lang="vi">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tiêu đề Trang Web</title>
</head>
<body>
    <!-- Nội dung trang web ở đây -->
</body>
</html>
THỰC HÀNH TỪNG BƯỚC (60 Phút)
Bước 1 Tạo File HTML
  1. Mở VS Code
  2. Tạo folder mới: TeeGenZ_Project
  3. Tạo file mới: index.html
  4. ! rồi ấn Tab để tự động sinh khung HTML5
Bước 2 Copy Code Dưới Đây Vào Body
index.html - Nội dung body
<header>
    <h1>TeeGenZ 👕</h1>
    <nav>
        <ul>
            <li><a href="#">Trang chủ</a></li>
            <li><a href="#">Mẫu áo</a></li>
            <li><a href="#">Bảng giá</a></li>
            <li><a href="#">Giỏ hàng (0)</a></li>
        </ul>
    </nav>
</header>

<hr>

<section>
    <h2>In Áo Thun Thể Hiện Cá Tính Của Bạn</h2>
    <p>Tự do thiết kế, in ấn sắc nét, giao hàng toàn quốc chỉ trong 2 ngày.</p>
    <button>Khám phá các mẫu áo</button>
</section>

<hr>

<section>
    <h2>Các Mẫu Áo Phôi Bán Chạy</h2>

    <div>
        <img src="https://images.unsplash.com/photo-1521572163474-6864f9cf17ab?w=300" alt="Áo thun trắng basic" width="200">
        <h3>Áo Thun Trắng Basic</h3>
        <p>Giá: 150.000 VNĐ</p>
        <button>Thêm vào giỏ</button>
    </div>

    <br>

    <div>
        <img src="https://images.unsplash.com/photo-1556821840-3a63f95609a7?w=300" alt="Áo Hoodie đen" width="200">
        <h3>Áo Hoodie Đen Dày Dặn</h3>
        <p>Giá: 350.000 VNĐ</p>
        <button>Thêm vào giỏ</button>
    </div>
</section>

<hr>

<footer>
    <h2>Bạn đã có thiết kế riêng?</h2>
    <p>Hãy tải file ảnh của bạn lên đây, chúng tôi sẽ in nó lên áo!</p>
    
    <form action="#">
        <label for="customerName">Tên của bạn:</label>
        <input type="text" id="customerName" placeholder="Nhập tên..."><br><br>

        <label for="designFile">Tải ảnh thiết kế (PNG/JPG):</label>
        <input type="file" id="designFile"><br><br>

        <button type="submit">Gửi yêu cầu in</button>
    </form>

    <br>
    <p>© 2026 Bản quyền thuộc về TeeGenZ.</p>
</footer>
Bước 3 Lưu File & Chạy Live Server
  1. Nhấn Ctrl + S để lưu file
  2. Chuột phải vào file → Chọn "Open with Live Server"
  3. Trình duyệt sẽ mở tự động tại http://localhost:5500
  4. Khi sửa code, trang web sẽ cập nhật tự động!
💡 Lưu Ý Quan Trọng
  • Giao diện sẽ trông xấu khi chưa có CSS - Điều này là BÌNH THƯỜNG!
  • Ở Buổi 2, chúng ta sẽ dùng CSS để trang trí và làm đẹp
  • Học sinh hay quên thẻ đóng - kiểm tra kỹ mỗi thẻ mở đều có thẻ đóng
  • Khuyến khích học sinh thay đổi nội dung: Đổi tên áo, link ảnh, v.v. để thấy sự thay đổi tức thì
KIẾN THỨC MỞ RỘNG
Các Thẻ HTML Thường Gặp Khác:
  • <div> - Tạo khối chứa nội dung (dùng để bao bọc và tổ chức)
  • <span> - Tạo khối inline (dùng bên trong đoạn văn)
  • <ul> <li> - Danh sách dấu chấm
  • <ol> <li> - Danh sách có số thứ tự
  • <strong> - In đậm (semantic)
  • <em> - In nghiêng (semantic)

Buổi 2: Đổ Khuôn Giao Diện & Trang Trí (CSS & Box Model)

🎯 Mục Tiêu: Nếu HTML là gạch xây nhà, thì CSS chính là lớp sơn, giấy dán tường và cách bố trí nội thất để ngôi nhà đẹp mắt.
LÝ THUYẾT CỐT LÕI (15 Phút)
1️⃣ Cách Nhúng CSS Vào HTML
Thêm vào thẻ <head>
<link rel="stylesheet" href="style.css">
2️⃣ Cú Pháp CSS - Quy Tắc "Chọn → Đổi → Thành"
h1 {
    color: red;          /* Chọn: h1, Đổi: màu chữ, Thành: đỏ */
    font-size: 32px;     /* Chọn: h1, Đổi: kích cỡ chữ, Thành: 32px */
}
3️⃣ CSS Box Model - Mô Hình Hộp (Quan Trọng Nhất!)

Mọi thứ trên web đều là hộp hình chữ nhật. Hộp có 4 lớp:

Content
  • Content (Nội dung): Chữ, ảnh, v.v.
  • Padding (Vùng đệm): Khoảng trống bên trong, giữa nội dung và viền
  • Border (Đường viền): Cạnh bên ngoài
  • Margin (Khoảng cách ngoài): Khoảng trống bên ngoài viền
4️⃣ Class & ID - "Biển Tên" Cho HTML

Để CSS không sơn nhầm chỗ, ta gắn "biển tên" (class/id) vào HTML:

<div class="product-card">
    <img src="...">
    <h3>Áo Thun Trắng Basic</h3>
    <p class="price">Giá: 150.000 VNĐ</p>
    <button class="btn-buy">Thêm vào giỏ</button>
</div>

/* CSS: Sơn các thẻ có class tương ứng */
.product-card { /* Chọn class product-card */ }
.price { /* Chọn class price */ }
.btn-buy { /* Chọn class btn-buy */ }
THỰC HÀNH TỪNG BƯỚC (60 Phút)
Bước 1 Cập Nhật File HTML - Thêm Class

Mở file index.html từ Buổi 1, tìm phần sản phẩm áo thun và cập nhật:

Cập nhật phần sản phẩm
<section>
    <h2>Các Mẫu Áo Phôi Bán Chạy</h2>

    <div class="product-card">
        <img src="https://images.unsplash.com/photo-1521572163474-6864f9cf17ab?w=300" alt="Áo thun trắng basic" width="200">
        <h3>Áo Thun Trắng Basic</h3>
        <p class="price">Giá: 150.000 VNĐ</p>
        <button class="btn-buy">Thêm vào giỏ</button>
    </div>

    <div class="product-card">
        <img src="https://images.unsplash.com/photo-1556821840-3a63f95609a7?w=300" alt="Áo Hoodie đen" width="200">
        <h3>Áo Hoodie Đen Dày Dặn</h3>
        <p class="price">Giá: 350.000 VNĐ</p>
        <button class="btn-buy">Thêm vào giỏ</button>
    </div>
</section>
Bước 2 Tạo File CSS
  1. Tạo file mới: style.css cùng thư mục với index.html
  2. Copy đoạn CSS dưới đây vào file
style.css - Buổi 2
/* 1. RESET CSS (Xóa lề thừa mặc định) */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: Arial, sans-serif;
}

body {
    background-color: #f4f4f9;
    color: #333;
}

/* 2. TRANG TRÍ HEADER */
header {
    background-color: #111;
    color: #fff;
    padding: 20px;
    text-align: center;
}

header a {
    color: #f39c12;
    text-decoration: none;
    margin: 0 15px;
    font-weight: bold;
}

/* 3. TRANG TRÍ BANNER */
section {
    padding: 40px 20px;
    text-align: center;
}

/* 4. TRANG TRÍ THẺ SẢN PHẨM - BOX MODEL THỰC CHIẾN */
.product-card {
    background-color: white;
    width: 250px;
    margin: 20px auto;
    padding: 15px;          /* Đệm bên trong */
    border: 2px solid #ddd; /* Viền ngoài */
    border-radius: 10px;    /* Bo góc */
}

.product-card img {
    border-radius: 8px;
}

.price {
    color: #e74c3c;
    font-weight: bold;
    margin: 10px 0;
}

/* 5. TRANG TRÍ NÚT MUA HÀNG */
.btn-buy {
    background-color: #f39c12;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
}

/* Hiệu ứng khi di chuột vào nút */
.btn-buy:hover {
    background-color: #d68910;
}
💡 Lưu Ý Quan Trọng
  • Thứ tự import CSS: File style.css của mình phải được link DƯỚI bootstrap (nếu dùng)
  • Margin vs Padding: Margin = đẩy ra ngoài, Padding = khoảng trống bên trong
  • box-sizing: border-box: Rất quan trọng! Giúp padding không làm hộp to ra
  • Hiệu ứng Hover: Dạy học sinh cách thay đổi border-radius, margin, padding để thấy sự thay đổi

Buổi 3: Dàn Trang & Responsive Design (Flexbox, Grid, Bootstrap)

🎯 Mục Tiêu: Làm cho trang web xếp ngang hàng (desktop) và co giãn trên điện thoại (mobile)
LÝ THUYẾT CỐT LÕI (15 Phút)
1️⃣ Container & Item - "Mẹ Bọc Con"

Flexbox và Grid đều tuân theo nguyên tắc: Cần một thẻ cha (Container) bao bọc các thẻ con (Items)

<div class="product-list">  <!-- Container -->
    <div class="product-card">...</div>  <!-- Item 1 -->
    <div class="product-card">...</div>  <!-- Item 2 -->
    <div class="product-card">...</div>  <!-- Item 3 -->
</div>
2️⃣ Flexbox (1 Chiều) vs Grid (2 Chiều)
Tính Năng Flexbox Grid
Số chiều 1 chiều (hàng hoặc cột) 2 chiều (hàng + cột)
Dùng cho Menu, thanh điều hướng Danh sách sản phẩm
Ví dụ display: flex; display: grid;
3️⃣ Bootstrap 5 - "Mì Ăn Liền" CSS

Thay vì tự viết CSS từng chút một, dùng Bootstrap để có class sẵn:

<!-- Nhúng Bootstrap vào <head> -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">

<!-- Sử dụng class của Bootstrap -->
<button class="btn btn-warning fw-bold">Nút vàng đậm</button>
<div class="container text-center">Căn giữa</div>
4️⃣ Media Query - Làm Responsive

Khi màn hình co lại, layout cần tự động thích ứng:

@media (max-width: 768px) {
    /* CSS này chỉ chạy khi màn hình nhỏ hơn 768px (Điện thoại) */
    .product-list {
        grid-template-columns: 1fr; /* Từ 3 cột → 1 cột */
    }
}
THỰC HÀNH TỪNG BƯỚC (60 Phút)
Bước 1 Cập Nhật HTML - Nhúng Bootstrap & Thêm Class
Thêm vào <head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="style.css">

Thêm class vào các phần:

Thêm vào body
<section>
    <h2 class="text-center mb-4">Các Mẫu Áo Phôi Bán Chạy</h2>
    <div class="product-list"> <!-- Container -->

        <div class="product-card">...</div>
        <div class="product-card">...</div>

    </div>
</section>
Bước 2 Cập Nhật CSS - Thêm Flexbox & Grid

Thêm đoạn này vào cuối file style.css:

style.css - Thêm phần Buổi 3
/* ================== BUỔI 3: FLEXBOX & GRID ================== */

/* 1. Flexbox cho Header */
header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 15px 40px;
}

header nav ul {
    display: flex;
    list-style: none;
}

/* 2. Grid cho Sản phẩm */
.product-list {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    padding: 0 40px;
}

.product-card {
    margin: 0;
    width: 100%;
}

/* 3. RESPONSIVE - Khi màn hình nhỏ */
@media (max-width: 768px) {
    header {
        flex-direction: column;
    }
    
    .product-list {
        grid-template-columns: 1fr;
        padding: 0 15px;
    }
}
Cách Kiểm Tra Responsive
  1. Mở trình duyệt → Nhấn F12
  2. Click biểu tượng Toggle device toolbar (mộp điện thoại)
  3. Kéo mép màn hình nhỏ lại từ từ
  4. Khi qua mốc 768px, layout sẽ tự động biến đổi!

Buổi 4: Lập Trình Tương Tác (JavaScript DOM)

🎯 Mục Tiêu: JavaScript = Bộ não của website. Bấm nút → Giỏ hàng tăng số
LÝ THUYẾT CỐT LÕI (15 Phút)
1️⃣ Biến (Variable) - Cái Hộp Lưu Số

Biến như một cái hộp có dán nhãn, lưu trữ dữ liệu tạm thời:

let cartQuantity = 0;      // Biến chứa số lượng giỏ hàng, ban đầu = 0
let userName = "An";       // Biến chứa tên
let isLoggedIn = true;    // Biến chứa true/false
2️⃣ DOM (Document Object Model) - Cầu Nối HTML ↔ JavaScript

JavaScript không tự biết HTML ở đâu. DOM là cầu nối:

/* Tìm kiếm (Query) */
const spanCartCount = document.getElementById("cartCount");
const buttons = document.querySelectorAll(".btn-buy");

/* Hành động (Action) */
spanCartCount.innerText = "5";  // Đổi chữ trong span
button.style.color = "red";     // Đổi màu nút
3️⃣ Sự Kiện (Event) - Máy Nghe Lén

Gắn "máy nghe lén" vào nút, khi click sẽ chạy code:

button.addEventListener("click", function() {
    // Code ở đây chạy khi nút được click
    cartQuantity = cartQuantity + 1;
    console.log("Giỏ hàng:", cartQuantity);
});
4️⃣ forEach - Vòng Lặp Qua Danh Sách

Khi có nhiều nút, không thể gắn sự kiện cho từng cái một. Dùng forEach:

const buttons = document.querySelectorAll(".btn-buy");

buttons.forEach(function(button) {
    button.addEventListener("click", function() {
        // Code này sẽ chạy cho TỪNG nút
        console.log("Nút được bấm!");
    });
});
THỰC HÀNH TỪNG BƯỚC (60 Phút)
Bước 1 Cập Nhật HTML - Gắn ID & Nhúng JS

Mở index.html, tìm phần Giỏ hàng trong Header:

Cập nhật Header
<header>
    <h1>TeeGenZ 👕</h1>
    <nav>
        <ul>
            <li><a href="#">Trang chủ</a></li>
            <li><a href="#">Mẫu áo</a></li>
            <li><a href="#" class="fw-bold text-warning">
                Giỏ hàng (<span id="cartCountDisplay">0</span>)
            </a></li>
        </ul>
    </nav>
</header>

Cuối file HTML, ngay trước </body>, thêm:

Nhúng file JS - Ngay trước </body>
    <script src="script.js"></script>
</body>
Bước 2 Tạo File JavaScript
  1. Tạo file: script.js cùng thư mục với index.html
  2. Copy đoạn code dưới vào
script.js - Buổi 4
// ==========================================
// BƯỚC 1: KHAI BÁO BIẾN LƯU SỐ LƯỢNG ÁO
// ==========================================
let cartQuantity = 0;

// ==========================================
// BƯỚC 2: TÌM CÁC THÀNH PHẦN TRÊN HTML
// ==========================================
const spanCartCount = document.getElementById("cartCountDisplay");
const buyButtons = document.querySelectorAll(".btn-buy");

// ==========================================
// BƯỚC 3: GẮN SỰ KIỆN CLICK CHO CÁC NÚT
// ==========================================
buyButtons.forEach(function(button) {
    button.addEventListener("click", function() {
        // 3.1. Tăng số lượng lên 1
        cartQuantity = cartQuantity + 1;
        
        // 3.2. Cập nhật lại thẻ HTML
        spanCartCount.innerText = cartQuantity;
        
        // 3.3. Hiện thông báo
        alert("Tuyệt vời! Bạn vừa thêm 1 chiếc áo vào giỏ hàng 👕");
    });
});
Debug - Cách Tìm Lỗi
  1. Mở trình duyệt → Nhấn F12 → Tab Console
  2. Nếu có lỗi chữ đỏ, kiểm tra file JS xem sai chính tả ở dòng nào
  3. Học sinh hay quên: chữ document, getElementById, v.v.
  4. Lưu ý: innerText (không phải innerHTML) để thay đổi chữ

Buổi 5: Đưa Lên Internet (GitHub Pages & Vấn Đáp)

🎯 Mục Tiêu: Từ code offline → Website online với link .github.io
LÝ THUYẾT CỐT LÕI (15 Phút)
1️⃣ Website Sống Ở Đâu?
❌ Hiện Tại (Offline)

Code chạy trong máy tính nhà mình, chỉ mình thấy

✅ GitHub Pages (Online)

Code lưu trên máy chủ của GitHub, ai cũng truy cập được qua link

2️⃣ GitHub Là Gì?
  • Mạng xã hội của lập trình viên (như Facebook nhưng của dev)
  • Lưu trữ code (như Google Drive)
  • Chia sẻ code với nhau
  • GitHub Pages = Tính năng biến code thành website
3️⃣ 3 Khái Niệm Quan Trọng
Repository (Kho Chứa) Thư mục lưu trữ code trên GitHub (giống folder)
Commit (Chốt Lưu) Lưu thay đổi vào kho chứa (checkpoint)
GitHub Pages Bật tính năng này để biến repo thành website
THỰC HÀNH TỪNG BƯỚC (45 Phút)
Bước 1 Tạo Tài Khoản & Repository Trên GitHub
  1. Truy cập github.com
  2. Nhấn Sign Up (nếu chưa có tài khoản)
  3. Sau khi đăng nhập, nhấn New Repository (nút xanh)
  4. Điền thông tin:
    • Repository name: teegenz-shop (không viết hoa, không dấu)
    • Description: "Trang web xưởng in áo thun"
    • Public (chọn để ai cũng xem được)
    • Nhấn Create repository
Bước 2 Đưa Code Lên GitHub (Upload)
  1. Trong trang Repository vừa tạo, tìm dòng chữ "uploading an existing file"
  2. Click vào → Khung kéo thả sẽ hiện ra
  3. Kéo 3 file từ máy tính thả vào:
    • index.html
    • style.css
    • script.js
  4. Đợi chút để upload xong
  5. Nhấn nút Commit changes (xanh lá)
Bước 3 Bật GitHub Pages
  1. Trong Repository, click tab Settings (hình bánh răng)
  2. Menu bên trái, chọn Pages
  3. Ở phần "Build and deployment" → "Source", chọn main (từ sổ xuống)
  4. Nhấn Save
  5. Đợi 1-2 phút để GitHub xử lý
  6. Tải lại trang (F5), sẽ thấy thông báo xanh:
    Your site is live at https://[tên-của-em].github.io/teegenz-shop
✅ Thành Công!

Click vào link và tận hưởng! Website của em đã lên mạng rồi 🎉

PHẦN VẤN ĐÁP (30 Phút)

Anh/cô giáo đóng vai "Khách hàng" và hỏi học sinh những câu sau:

Câu 1 - HTML Cấu Trúc & Ngữ Nghĩa

Hỏi: "Em thấy form ở cuối trang có tên và file upload. Nếu thầy muốn thêm ô nhập 'Số điện thoại', em sẽ gõ code gì và chèn vào dòng nào?"

Kỳ vọng: Học sinh biết tìm thẻ <form>, viết <input type="tel"> hoặc <input type="number">

Câu 2 - CSS Box Model & Margin/Padding

Hỏi: "Thầy thấy các thẻ áo thun dính sát vào nhau (nếu trên mobile). Em đã học Box Model rồi, vậy em dùng Margin hay Padding để đẩy chúng cách xa? Sửa ở class nào?"

Kỳ vọng: Học sinh biết Margin (đẩy ra ngoài), chỉ ra class .product-card

Câu 3 - CSS Grid & Responsive

Hỏi: "Làm sao trang web của em biết khi nào màn hình bị nhỏ lại để chuyển từ 3 cột thành 1 cột? Giải thích dòng code đó."

Kỳ vọng: Học sinh chỉ vào @media (max-width: 768px) và giải thích grid-template-columns

Câu 4 - JavaScript DOM & Event Listener

Hỏi: "Giải thích: Bằng phép màu gì khi thầy bấm nút 'Thêm vào giỏ', con số trên Menu lại tăng lên? Dùng hàm nào để tìm tất cả nút bấm?"

Kỳ vọng: Học sinh chỉ vào script.js, giải thích 3 bước:

  • querySelectorAll(".btn-buy") = Tìm tất cả nút
  • forEach = Duyệt từng nút
  • addEventListener("click") = Gắn máy nghe lén
  • Tăng cartQuantity → Gán lại vào DOM

🎉 Kết Thúc Khóa Học

Học sinh vừa hoàn thành chặng đường HTML → CSS → JavaScript → Deploy!

Định hướng tương lai: Sau này học tiếp Backend (Python/Node.js) + Database, sẽ có thể làm giỏ hàng lưu vĩnh viễn, đặt hàng, v.v. giống hệ thống thực tế!

Buổi 6: Quản Lý Dữ Liệu & localStorage

🎯 Mục Tiêu: Lưu dữ liệu giỏ hàng trên máy tính, khi F5 trang web vẫn có dữ liệu
LÝ THUYẾT CỐT LÕI (15 Phút)
1️⃣ localStorage - Kho Lưu Trữ Trên Máy Tính
// Lưu dữ liệu
localStorage.setItem("cartItems", "5");

// Lấy dữ liệu
const items = localStorage.getItem("cartItems");
console.log(items); // "5"

// Xóa dữ liệu
localStorage.removeItem("cartItems");

// Xóa tất cả
localStorage.clear();
2️⃣ JSON - Biến Object Thành String

localStorage chỉ lưu string, nên cần convert Object → JSON:

// Object
const cart = { items: 5, total: 500000 };

// Convert thành JSON string
const jsonString = JSON.stringify(cart);
localStorage.setItem("myCart", jsonString);

// Lấy lại và convert thành Object
const retrieved = localStorage.getItem("myCart");
const cartObject = JSON.parse(retrieved);
console.log(cartObject.items); // 5
3️⃣ Flow Control - if/else & for

Kiểm tra điều kiện và lặp qua mảng:

// if/else
if (localStorage.getItem("cartItems")) {
    console.log("Có dữ liệu lưu");
} else {
    console.log("Chưa có dữ liệu");
}

// for lặp qua mảng
const products = ["Áo 1", "Áo 2", "Áo 3"];
for (let i = 0; i < products.length; i++) {
    console.log(products[i]);
}
4️⃣ Array Methods - map, filter, reduce
const products = [
    { name: "Áo 1", price: 150000 },
    { name: "Áo 2", price: 200000 },
];

// map: biến đổi mảng
const prices = products.map(p => p.price);
console.log(prices); // [150000, 200000]

// filter: lọc phần tử
const expensive = products.filter(p => p.price > 150000);

// reduce: gộp thành 1 giá trị
const total = products.reduce((sum, p) => sum + p.price, 0);
THỰC HÀNH - NÂNG CẬP GIỎ HÀNG
Bước 1 Cập Nhật script.js - Lưu Vào localStorage
script.js - Buổi 6
// Lấy từ localStorage, nếu không có thì mặc định = 0
let cartQuantity = JSON.parse(localStorage.getItem("cartQuantity")) || 0;

const spanCartCount = document.getElementById("cartCountDisplay");
const buyButtons = document.querySelectorAll(".btn-buy");

// Cập nhật giao diện từ localStorage
spanCartCount.innerText = cartQuantity;

buyButtons.forEach(button => {
    button.addEventListener("click", function() {
        // Tăng số lượng
        cartQuantity = cartQuantity + 1;
        
        // Lưu vào localStorage
        localStorage.setItem("cartQuantity", JSON.stringify(cartQuantity));
        
        // Cập nhật giao diện
        spanCartCount.innerText = cartQuantity;
        
        alert("Thêm vào giỏ! Tổng: " + cartQuantity);
    });
});
🧪 Kiểm Thử
  1. Mở Developer Tools (F12) → Tab "Application" → localStorage
  2. Bấm nút "Thêm vào giỏ"
  3. Trong localStorage sẽ thấy key "cartQuantity" với giá trị số
  4. F5 tải lại trang - số lượng giỏ hàng vẫn được giữ! 🎉

Buổi 7: ES6 Modern JavaScript & Modules

🎯 Mục Tiêu: Viết JavaScript hiện đại, sạch sẽ và tách code thành module
LÝ THUYẾT CỐT LÕI (15 Phút)
1️⃣ Template Literals - Chuỗi Thông Minh
// Cách cũ (ES5)
const name = "An";
const msg = "Xin chào " + name + "!";

// Cách mới (ES6) - dùng backtick
const msg = \`Xin chào \${name}!\`;
console.log(msg); // "Xin chào An!"
2️⃣ Arrow Functions - Hàm Mũi Tên
// Cách cũ
function add(a, b) {
    return a + b;
}

// Cách mới
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5

// Với forEach
products.forEach(p => console.log(p));
3️⃣ Destructuring - Bóc Tách Biến
// Object
const product = { name: "Áo", price: 150000 };
const { name, price } = product;
console.log(name); // "Áo"

// Array
const colors = ["red", "green", "blue"];
const [first, second] = colors;
console.log(first); // "red"
4️⃣ Modules - import/export
// utils.js
export function formatCurrency(num) {
    return num.toLocaleString('vi-VN') + " VNĐ";
}

// script.js
import { formatCurrency } from './utils.js';
console.log(formatCurrency(150000)); // "150.000 VNĐ"
5️⃣ Spread Operator - Lan Tỏa
// Mảng
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

// Object
const user = { name: "An", age: 16 };
const newUser = { ...user, city: "Hà Nội" };
// { name: "An", age: 16, city: "Hà Nội" }
THỰC HÀNH - VIẾT LẠI BẰNG ES6
Bước 1 Tạo File utils.js - Hàm Dùng Chung
utils.js
// Định dạng tiền tệ
export const formatCurrency = (num) => {
    return num.toLocaleString('vi-VN') + " VNĐ";
};

// Lấy năm hiện tại
export const getCurrentYear = () => new Date().getFullYear();

// Kiểm tra email
export const isValidEmail = (email) => {
    return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);
};
Bước 2 Cập Nhật script.js - Sử Dụng ES6
script.js - ES6 Version
// import các hàm
import { formatCurrency, getCurrentYear } from './utils.js';

// Khai báo biến
let cartQuantity = JSON.parse(localStorage.getItem("cartQuantity")) || 0;

// DOM Query
const spanCartCount = document.getElementById("cartCountDisplay");
const buyButtons = document.querySelectorAll(".btn-buy");

// Khởi tạo
spanCartCount.innerText = cartQuantity;

// Arrow function để xử lý click
buyButtons.forEach(button => {
    button.addEventListener("click", () => {
        cartQuantity++;
        localStorage.setItem("cartQuantity", JSON.stringify(cartQuantity));
        spanCartCount.innerText = cartQuantity;
        alert(\`Thêm vào giỏ! Tổng: \${cartQuantity}\`);
    });
});
Bước 3 Cập Nhật HTML - Thêm type="module"
index.html - cuối file
<!-- Đổi từ cái cũ -->
<script src="script.js"></script>

<!-- Thành ES6 Module -->
<script type="module" src="script.js"></script>
🎯 Ưu Điểm ES6 Modules
  • ✅ Code dễ đọc hơn (arrow functions, template literals)
  • ✅ Tái sử dụng code (import/export)
  • ✅ Quản lý biến tốt hơn (scope)
  • ✅ Chuẩn bị sẵn cho các framework như React, Vue

Bài Tập Nâng Cao & Mở Rộng

💪 Thử Thách: Những bài tập này giúp bạn trở thành lập trình viên thực thụ!
🔧 Bài Tập Nâng Cao - HTML & CSS
1. HTML Semantic (Bài 2 nâng cao)
  • Thay <div> thành <header>, <nav>, <main>, <section>, <article>, <footer>
  • Thêm <img alt=""> cho tất cả hình ảnh (SEO)
  • Dùng <figure><figcaption> cho hình ảnh có chú thích
2. CSS Box Model Nâng Cao (Bài 4)
  • Làm Header sticky: position: sticky; top: 0;
  • Thêm hiệu ứng Shadow: box-shadow: 0 4px 6px rgba(0,0,0,0.1);
  • Làm Button có transition: transition: all 0.3s ease;
3. Position & Transform
  • Tạo Modal (popup) bằng position: fixed
  • Thêm icon loading spinner bằng animation
  • Làm Carousel (slide) ảnh
📱 Bài Tập Nâng Cao - JavaScript
1. Tìm Kiếm & Lọc Sản Phẩm (Bài 8)
  • Thêm ô input tìm kiếm
  • Dùng .filter() để lọc sản phẩm theo tên
  • Lọc theo giá: từ 100k → 500k
2. Tính Năng Giỏ Hàng Đầy Đủ (Bài 9-11)
  • Lưu giỏ hàng dạng mảng object: [{id, name, price, qty}]
  • Tính tổng tiền: .reduce((sum, item) => sum + item.price * item.qty, 0)
  • Tăng/giảm số lượng sản phẩm trong giỏ
  • Xóa sản phẩm khỏi giỏ hàng
3. Validation Form (Nâng Cao)
  • Kiểm tra Email hợp lệ (regex)
  • Kiểm tra Số điện thoại Việt Nam (10 số, bắt đầu 0)
  • Hiển thị lỗi inline (dưới từng ô input)
💾 Bài Tập Nâng Cao - Quản Lý Dữ Liệu
1. Sử Dụng localStorage Nâng Cao
  • Lưu toàn bộ giỏ hàng thành JSON
  • Thêm tính năng "Lịch sử mua hàng" lưu trên máy
  • Tạo nút "Xóa tất cả dữ liệu" (confirm trước)
2. Mock Data & Rendering (Bài 9)
  • Tạo file data/products.js chứa mảng 10 sản phẩm
  • Dùng .map() để render HTML từ dữ liệu
  • Thay thế HTML cứng thành động HTML
3. Pagination (Phân Trang)
  • Hiển thị 6 sản phẩm/trang
  • Thêm nút "Trang trước" / "Trang sau"
  • Hiển thị "Trang 1/5"
✨ Bài Tập Nâng Cao - UX/UI & Hiệu Năng
1. Toast Notification
  • Thay alert() bằng popup tùy chỉnh
  • Hiển thị 3 giây rồi tự động ẩn
  • Style đẹp với icon check/error
2. Loading & Skeleton
  • Thêm loading spinner khi tải dữ liệu
  • Dùng Skeleton screen (placeholder xám)
  • Animate khi HTML render
3. Dark Mode
  • Thêm nút toggle Dark/Light mode
  • Lưu preferences vào localStorage
  • Dùng CSS variables: --primary-color
🏆 Dự Án Hoàn Chỉnh - Checklist
Sau khi hoàn thành, website của bạn sẽ có:
  • ✅ HTML semantic & cấu trúc tốt
  • ✅ CSS đẹp & responsive trên mobile
  • ✅ Giỏ hàng lưu dữ liệu trên máy
  • ✅ Tìm kiếm & lọc sản phẩm
  • ✅ Pagination / phân trang
  • ✅ Form validation & xử lý lỗi
  • ✅ Code ES6 modern & modules
  • ✅ Dark mode toggle
  • ✅ Toast notification
  • ✅ Deploy lên GitHub Pages 🚀