【JavaScript】day28-events-project

作者:mario 发布时间: 2026-08-26 阅读量:3 评论数:0

第二十八天:事件与综合项目 — 响应交互的"设备管理系统"

蜗牛往上爬 · 前端工业可视化学习笔记 第 28 篇
DOM 让 JS 能改页面,事件让页面能"响应"用户——点击、输入、键盘。今天学 addEventListener、事件对象、事件冒泡与委托,最后用全部所学(对象数组 + DOM + 事件)完成 JS 基础收官项目:设备管理系统(增删改查)


目录


一、addEventListener 添加监听

var btn = document.getElementById("add-btn");

// 添加监听
btn.addEventListener("click", function () {
  console.log("按钮被点击");
});

addEventListener vs onclick

// onclick:只能绑一个(后者覆盖前者)
btn.onclick = fn1;
btn.onclick = fn2;  // 覆盖 fn1

// addEventListener:能绑多个(都执行)
btn.addEventListener("click", fn1);
btn.addEventListener("click", fn2);  // 两个都执行

推荐 addEventListener:可绑多个、可移除(removeEventListener)。


二、常用事件速查

// 鼠标事件
element.addEventListener("click", fn);     // 单击
element.addEventListener("dblclick", fn);  // 双击
element.addEventListener("mouseover", fn); // 移入
element.addEventListener("mouseout", fn);  // 移出

// 键盘事件
document.addEventListener("keydown", function (e) {
  console.log(e.key);  // "Enter"、"a"...
  if (e.key === "Enter") { /* 回车 */ }
});

// 表单事件
input.addEventListener("input", function (e) {
  console.log(e.target.value);  // 实时输入值
});
form.addEventListener("submit", function (e) {
  e.preventDefault();  // ⭐ 阻止表单默认提交(刷新页面)
  // 处理提交
});

// 窗口事件
window.addEventListener("resize", fn);  // 窗口大小变化

三、事件对象 event

card.addEventListener("click", function (event) {
  event.target;           // 实际被点击的元素
  event.currentTarget;    // 绑定监听的元素
  event.type;             // "click"

  event.preventDefault();   // 阻止默认行为(a 跳转、表单提交)
  event.stopPropagation();  // 阻止冒泡
});

四、事件冒泡与事件委托

冒泡:点击子元素,事件会一路冒泡到父元素。

<div id="list">
  <div class="card">设备A</div>
  <div class="card">设备B</div>
</div>
// 点击"设备A"时冒泡顺序:card → #list → body → ... → document

// ⭐ 事件委托:把监听绑到父元素,处理所有子元素
var list = document.getElementById("list");
list.addEventListener("click", function (event) {
  var target = event.target;
  if (target.classList.contains("card")) {
    console.log("点击了:" + target.textContent);
  }
});

// 之后动态添加的新卡片,无需再绑定,自动生效 ✅
var newCard = document.createElement("div");
newCard.className = "card";
newCard.textContent = "设备C";
list.appendChild(newCard);  // 点击它也能触发上面的监听

事件委托的价值

  1. 动态添加的元素自动响应

  2. 几百个卡片只绑 1 个监听(性能好)

  3. 代码简洁


五、定时器:让数据动起来

// setTimeout:延迟一次
setTimeout(function () { console.log("3 秒后"); }, 3000);

// setInterval:周期执行
var timer = setInterval(function () { console.log("每秒一次"); }, 1000);
clearInterval(timer);  // 停止

// 实战:大屏时间实时更新
function updateTime() {
  document.getElementById("current-time").textContent =
    new Date().toLocaleString();
}
updateTime();
setInterval(updateTime, 1000);

六、综合项目:设备管理系统

JS 基础收官项目——对象数组 + DOM + 事件 + 事件委托的完整应用。

HTML

<h1>设备管理系统</h1>

<!-- 添加表单 -->
<form id="device-form">
  <input id="input-id" placeholder="设备编号" required>
  <input id="input-name" placeholder="设备名称" required>
  <button type="submit">添加</button>
</form>

<!-- 搜索 -->
<input id="search-input" placeholder="搜索设备名称...">

<!-- 列表 -->
<ul id="device-list"></ul>

<script src="device-manager.js"></script>

JS

// ========== 数据层 ==========
var devices = [
  { id: "CNC-001", name: "数控机床" },
  { id: "AGV-002", name: "搬运机器人" }
];

// ========== 渲染层 ==========
function render(filterText) {
  var list = document.getElementById("device-list");
  list.innerHTML = "";

  // 搜索过滤
  var data = filterText
    ? devices.filter(function (d) {
        return d.name.indexOf(filterText) !== -1;
      })
    : devices;

  // 渲染
  data.forEach(function (device) {
    var li = document.createElement("li");
    li.innerHTML =
      "<span>" + device.id + " - " + device.name + "</span>" +
      "<button class='del' data-id='" + device.id + "'>删除</button>";
    list.appendChild(li);
  });
}

// ========== 添加设备 ==========
document.getElementById("device-form").addEventListener("submit", function (e) {
  e.preventDefault();  // 阻止刷新

  var id = document.getElementById("input-id").value.trim();
  var name = document.getElementById("input-name").value.trim();
  if (!id || !name) return alert("编号和名称不能为空");

  // 查重
  if (devices.some(function (d) { return d.id === id; })) {
    return alert("编号已存在");
  }

  devices.push({ id: id, name: name });
  this.reset();
  render();
});

// ========== 删除设备(事件委托)==========
document.getElementById("device-list").addEventListener("click", function (e) {
  if (!e.target.classList.contains("del")) return;

  var id = e.target.getAttribute("data-id");
  devices = devices.filter(function (d) { return d.id !== id; });
  render();
});

// ========== 搜索 ==========
document.getElementById("search-input").addEventListener("input", function (e) {
  render(e.target.value.trim());
});

// 首次渲染
render();

这个项目用到的知识点

功能

用到的知识

数据存储

对象数组

添加

submit 事件 + preventDefault + push

删除

事件委托 + filter

搜索

input 事件 + indexOf

渲染

innerHTML 清空 + createElement + appendChild

查重

some + 数组方法


七、总结

概念

关键点

addEventListener

推荐,可绑多个

常用事件

click / input / submit / keydown

preventDefault

阻止默认行为(表单提交刷新)

冒泡

子元素事件传到父元素

事件委托

绑父元素处理子元素,动态元素自动生效

setInterval

周期执行,做实时刷新

增删改查

push / filter / indexOf / render 重新渲染

🎉 设备管理系统完成,JS 基础(语法 + 数据结构 + 逻辑 + DOM + 事件)全部收官!接下来进入 ES6 标准——用更现代简洁的语法(let/const、箭头函数、模板字符串)重写这些代码。

评论