简单来说, DOM事件就是发生在HTML元素上的"事情". 比如用户点击了一个按钮(click事件), 鼠标移动到了某个元素上(mouseover事件),或者表单被提交了(submit事件)等等.
事件系统让我们能够"监听"这些事件,并在它们发生时执行相应的JavaScript代码,从而实现网页的交互功能.
这个知识点很重要但容易被忽略! 当一个事件发生时,它会在DOM树中经历三个阶段:
- 捕获阶段: 从window对象一路向下,直到找到目标元素 
- 目标阶段: 到达实际触发事件的元素 
- 冒泡阶段: 从目标元素向上冒泡回window对象 
示例代码:
<div id="outer">  <button id="inner">点我</button></div>
<script>  const outer = document.getElementById('outer');  const inner = document.getElementById('inner');
    outer.addEventListener('click', () => {    console.log('捕获阶段-outer');  }, true);
    outer.addEventListener('click', () => {    console.log('冒泡阶段-outer');  });
  inner.addEventListener('click', () => {    console.log('目标阶段-inner');  });</script>
<button onclick="alert('你好!')">点击我</button>
缺点:
- HTML和JavaScript代码混在一起. 
- 不方便维护. 
- 只能添加一个处理函数. 
2)DOM属性写法:
const btn = document.querySelector('button');btn.onclick = function() {  console.log('第一次点击');};
btn.onclick = function() {  console.log('第二次点击');};
缺点:
3)addEventListener写法(推荐)
const btn = document.querySelector('button');
function firstClick() {  console.log('第一次点击');}
function secondClick() {  console.log('第二次点击');}
btn.addEventListener('click', firstClick);btn.addEventListener('click', secondClick);
btn.removeEventListener('click', firstClick);
优点:
三、事件对象
当事件发生时, 浏览器会创建一个事件对象(通常命名为event或e), 它包含了关于事件的所有信息.
常用属性和方法:
element.addEventListener('click', function(e) {    e.preventDefault();
    e.stopPropagation();
    e.stopImmediatePropagation();
    console.log(e.target);
    console.log(e.currentTarget);
    console.log(e.type);
    console.log(e.clientX, e.clientY);    console.log(e.pageX, e.pageY);      
    console.log(e.key);                   console.log(e.ctrlKey);             });
四、事件委托
事件委托是一种利用事件冒泡机制的技巧,它让我们不必为每个子元素单独添加事件监听,而是在父元素上设置一个监听器.
为什么用事件委托?
- 性能优化: 减少事件监听器数量 
- 动态元素: 对新添加的子元素自动生效 
- 内存节省: 减少内存占用 
示例:
<ul id="todo-list">  <li>买牛奶</li>  <li>写代码</li>  <li>遛狗</li></ul>
<script>  const list = document.getElementById('todo-list');
              
    list.addEventListener('click', function(e) {    if (e.target.tagName === 'LI') {      console.log(e.target.textContent);    }  });
    const newItem = document.createElement('li');  newItem.textContent = '学习事件委托';  list.appendChild(newItem);  </script>
五、自定义事件
除了浏览器内置的事件,我们还可以创建和触发自定义事件.
const event = new Event('myCustomEvent');
document.addEventListener('myCustomEvent', function() {  console.log('自定义事件触发了');});
document.dispatchEvent(event);
const event = new CustomEvent('build', {  detail: { time: new Date(), message: 'Hello World' }});
document.addEventListener('build', function(e) {  console.log('事件数据:', e.detail);});
document.dispatchEvent(event);
六、常见的事件类型
让我们看看一些常用的事件类型:
鼠标事件:
键盘事件:
- keydown-键按下.
 
- keyup-键释放.
 
- keypress-键按下并产生字符(已废弃).
 
 
 
表单事件:
其他:
七、其他使用技巧
防抖与节流:
function debounce(func, delay) {  let timeout;  return function() {    clearTimeout(timeout);    timeout = setTimeout(() => func.apply(this, arguments), delay);  };}
function throttle(func, limit) {  let inThrottle;  return function() {    if (!inThrottle) {      func.apply(this, arguments);      inThrottle = true;      setTimeout(() => inThrottle = false, limit);    }  };}
window.addEventListener('resize', debounce(function() {  console.log('窗口大小改变了');}, 200));
阅读原文:原文链接
该文章在 2025/7/17 10:08:47 编辑过