Chào mừng các bạn đến với Rcom Dăm Yi blog - Kho tài liệu bổ ích!, Chúng tôi sẽ từng bước hoàn thiện để bạn đọc cảm thấy hài lòng, hữu ích!

Thứ Sáu, 23 tháng 1, 2026

Bài 13: JavaScript Array & Object – Quản lý danh sách (thêm/xóa/tìm kiếm)

🎯 Mục tiêu

  • Hiểu Array (mảng) và Object (đối tượng) trong JavaScript
  • Biết dùng các hàm mảng: push, filter, map, find, splice
  • Biết render (vẽ) danh sách ra HTML bằng DOM
  • Tạo mini CRUD: Thêm / Xóa / Tìm kiếm
  • (Nâng cao) Lưu dữ liệu bằng localStorage

📘 Lý thuyết ngắn

1) Array (Mảng): danh sách nhiều phần tử.


const nums = [1, 2, 3];
nums.push(4); // thêm cuối
    

2) Object (Đối tượng): lưu dữ liệu theo cặp key–value.


const product = { id: 1, name: "Nước suối", price: 10000 };
console.log(product.name); // "Nước suối"
    

3) Mảng object (rất hay gặp trong web)


const products = [
  { id: 1, name: "Cà phê", price: 25000 },
  { id: 2, name: "Trà sữa", price: 35000 }
];
    

4) Các hàm mảng quan trọng

  • map(): biến đổi mảng → mảng mới
  • filter(): lọc theo điều kiện
  • find(): tìm 1 phần tử
  • splice(): xóa/sửa tại vị trí index

💻 Code mẫu (Mini app quản lý sản phẩm)


<!doctype html>
<html lang="vi">
<head>
  <meta charset="utf-8">
  <title>Bài 13 - Array & Object CRUD</title>

  <style>
    body{
      font-family: Arial;
      background:#f7f8fa;
      padding: 24px;
      line-height: 1.7;
    }
    .app{
      max-width: 860px;
      margin: 0 auto;
      background:#fff;
      border:1px solid #e5e5e5;
      border-radius: 14px;
      padding: 18px;
    }
    h1{ margin-top:0; text-align:center; }

    .grid{
      display:grid;
      grid-template-columns: 1fr 1fr 1fr auto;
      gap: 10px;
      margin: 12px 0;
    }
    @media (max-width: 800px){
      .grid{ grid-template-columns: 1fr 1fr; }
    }

    input{
      padding:10px 12px;
      border:1px solid #ddd;
      border-radius: 10px;
      width:100%;
      box-sizing:border-box;
    }

    button{
      padding:10px 14px;
      border:0;
      border-radius: 10px;
      cursor:pointer;
      background:#2563eb;
      color:#fff;
      font-weight:700;
    }
    button.gray{ background:#111; }
    button.red{ background:#ef4444; }

    .toolbar{
      display:flex;
      gap:10px;
      flex-wrap:wrap;
      align-items:center;
      justify-content: space-between;
      margin-top: 8px;
    }

    .table{
      width: 100%;
      border-collapse: collapse;
      margin-top: 12px;
    }
    .table th, .table td{
      border: 1px solid #ddd;
      padding: 10px;
      text-align:left;
      vertical-align: top;
    }
    .table th{
      background:#111;
      color:#fff;
    }

    .badge{
      display:inline-block;
      padding:2px 10px;
      border-radius: 999px;
      background:#eef2ff;
      border:1px solid #dbeafe;
      font-size: 12px;
      margin-right: 6px;
    }

    .msg{
      margin-top: 10px;
      padding: 10px 12px;
      border-radius: 12px;
      background:#f3f4f6;
      border:1px solid #e5e7eb;
      color:#111;
    }
  </style>
</head>

<body>

  <div class="app">
    <h1>🧾 Quản lý sản phẩm (Array + Object)</h1>

    <div class="grid">
      <input id="name" type="text" placeholder="Tên sản phẩm (vd: Trà sữa)">
      <input id="price" type="number" placeholder="Giá (vd: 35000)">
      <input id="category" type="text" placeholder="Danh mục (vd: Đồ uống)">
      <button id="btnAdd">Thêm</button>
    </div>

    <div class="toolbar">
      <div>
        <span class="badge">Thêm</span>
        <span class="badge">Xóa</span>
        <span class="badge">Tìm kiếm</span>
      </div>

      <div style="display:flex; gap:10px; flex-wrap:wrap;">
        <input id="search" type="text" placeholder="Tìm theo tên..." style="min-width:220px">
        <button class="gray" id="btnClear">Xóa hết</button>
      </div>
    </div>

    <table class="table">
      <thead>
        <tr>
          <th>ID</th>
          <th>Tên</th>
          <th>Danh mục</th>
          <th>Giá</th>
          <th>Thao tác</th>
        </tr>
      </thead>
      <tbody id="tbody"></tbody>
    </table>

    <div class="msg" id="msg">Sẵn sàng.</div>
  </div>

  <script>
    // ====== 1) Dữ liệu ban đầu (mảng object) ======
    let products = [
      { id: 1, name: "Cà phê", category: "Đồ uống", price: 25000 },
      { id: 2, name: "Trà sữa", category: "Đồ uống", price: 35000 },
      { id: 3, name: "Snack", category: "Ăn vặt", price: 15000 }
    ];

    // ====== 2) Lấy element ======
    const elName = document.getElementById("name");
    const elPrice = document.getElementById("price");
    const elCategory = document.getElementById("category");
    const btnAdd = document.getElementById("btnAdd");
    const elSearch = document.getElementById("search");
    const btnClear = document.getElementById("btnClear");
    const tbody = document.getElementById("tbody");
    const msg = document.getElementById("msg");

    // ====== 3) Helpers ======
    function formatMoney(n){
      return Number(n).toLocaleString("vi-VN") + " đ";
    }

    function setMsg(text){
      msg.textContent = text;
    }

    function nextId(){
      // lấy id lớn nhất + 1
      const maxId = products.length ? Math.max(...products.map(p => p.id)) : 0;
      return maxId + 1;
    }

    // ====== 4) Render ======
    function render(list){
      tbody.innerHTML = "";

      if(list.length === 0){
        tbody.innerHTML = '<tr><td colspan="5">Không có dữ liệu.</td></tr>';
        return;
      }

      list.forEach(p => {
        const tr = document.createElement("tr");

        tr.innerHTML = `
          <td>${p.id}</td>
          <td>${p.name}</td>
          <td>${p.category}</td>
          <td>${formatMoney(p.price)}</td>
          <td><button class="red" data-id="${p.id}">Xóa</button></td>
        `;

        tbody.appendChild(tr);
      });

      // gắn sự kiện xóa cho các nút vừa render
      tbody.querySelectorAll("button[data-id]").forEach(btn => {
        btn.addEventListener("click", () => {
          const id = Number(btn.dataset.id);
          removeById(id);
        });
      });
    }

    // ====== 5) Thêm ======
    function addProduct(){
      const name = elName.value.trim();
      const category = elCategory.value.trim();
      const price = Number(elPrice.value);

      if(name.length < 2){
        setMsg("❌ Tên sản phẩm quá ngắn.");
        return;
      }
      if(!category){
        setMsg("❌ Vui lòng nhập danh mục.");
        return;
      }
      if(!price || price <= 0){
        setMsg("❌ Giá không hợp lệ.");
        return;
      }

      const p = { id: nextId(), name, category, price };
      products.push(p); // push vào mảng

      elName.value = "";
      elCategory.value = "";
      elPrice.value = "";

      setMsg("✅ Đã thêm: " + p.name);
      applySearch(); // render theo filter hiện tại
    }

    // ====== 6) Xóa ======
    function removeById(id){
      const idx = products.findIndex(p => p.id === id);
      if(idx === -1) return;

      const removed = products[idx];
      products.splice(idx, 1); // xóa 1 phần tử tại idx

      setMsg("🗑️ Đã xóa: " + removed.name);
      applySearch();
    }

    // ====== 7) Tìm kiếm ======
    function applySearch(){
      const key = elSearch.value.trim().toLowerCase();
      if(!key){
        render(products);
        return;
      }
      const filtered = products.filter(p => p.name.toLowerCase().includes(key));
      render(filtered);
    }

    // ====== 8) Xóa hết ======
    function clearAll(){
      if(!confirm("Bạn chắc chắn muốn xóa hết dữ liệu?")) return;
      products = [];
      setMsg("Đã xóa hết dữ liệu.");
      applySearch();
    }

    // ====== 9) Gắn sự kiện ======
    btnAdd.addEventListener("click", addProduct);
    elSearch.addEventListener("input", applySearch);
    btnClear.addEventListener("click", clearAll);

    // ====== 10) Render lần đầu ======
    render(products);
  </script>

</body>
</html>
    

👉 Copy code → lưu thành bai13.html → mở bằng Chrome.
Thử thêm sản phẩm, gõ tìm kiếm, bấm xóa từng dòng.

✍️ Bài tập

  1. Thêm cột “Ngày tạo” (tự lấy ngày hiện tại bằng JS).
  2. Thêm chức năng “Sắp xếp theo giá tăng dần/giảm dần”.
  3. (Nâng cao) Lưu mảng products vào localStorage và tải lại vẫn còn.
  4. (Nâng cao) Thêm nút “Sửa” (edit) cho mỗi dòng.

✅ Đáp án gợi ý

1) Lưu localStorage (gợi ý)


// Lưu
localStorage.setItem("products", JSON.stringify(products));

// Tải
products = JSON.parse(localStorage.getItem("products") || "[]");
    

2) Sắp xếp tăng dần


products.sort((a,b) => a.price - b.price);
render(products);
    

Không có nhận xét nào:

Đăng nhận xét

Bài đăng phổ biến

💬 Bình luận

💬 Bình luận

📌 Danh sách bình luận