简述 DOM 事件模型或 DOM 事件机制

捕获:当用户点击按钮,浏览器会从 window 从上向下遍历至用户点击的按钮,逐个触发事件处理函数。
冒泡:浏览器从用户点击的按钮从下往上遍历至 window,逐个触发事件处理函数。
W3C 事件模型/事件机制:对每个事件先捕获再冒泡

简述事件委托

事件委托就是把事件监听放在祖先元素(如父元素、爷爷元素)上。
好处是:1 节约监听数量 2 可以监听动态生成的元素。

JS 的捕获和冒泡机制允许我们实现一种被称为事件委托的强大的事件处理模式。
基本想法是,如果我们有许多以类似方式处理的元素,那么就不必为每个元素分配一个处理程序 —— 而是将单个处理程序放在它们的共同祖先上。
事件委托的优点:
提高页面性能。
可以监听动态元素。
为什么说它更强大呢?举两个例子:

1. 假设给100个按钮添加点击事件

如果用 for 循环给每个按钮都监听一个事件函数,那么占用的内存就很多,可能会影响页面性能。
利用事件委托就可以指定一个事件处理程序管理某一类型的所有事件。
通俗的讲,就是把事情委托给这100个按钮的父元素,假定有一个 div 包裹这100个按钮,那么只需为 div 添加一个点击事件。
代码如下:

  1. // html代码
  2. <div id="div1">
  3. <button data-id="1">1</button>
  4. <button data-id="2">2</button>
  5. <button data-id="3">3</button>
  6. <button data-id="4">4</button>
  7. ****************
  8. </div>
  9. // js代码
  10. div1.addEventListener('click', (e)=>{
  11. const t = e.target
  12. if(t.tagName.toLowerCase() === 'button'){
  13. console.log('button'被点击了)
  14. console.log('button'内容是 + t.textContext) // 获取被点击元素的文本内容
  15. console.log('button 的data-id是:'+ t.dataset.id) // 获取被点击元素的dataset.id
  16. }
  17. })

2. 监听目前不存在的元素的点击事件

利用定时器做一个1秒后出现的 button,该如何为其绑定点击事件呢?同样是利用事件委托。
代码如下:http://js.jirengu.com/gajipigavu/1/edit?html,js,console,output

  1. // html代码
  2. <div id="div1">
  3. </div>
  4. // js代码
  5. setTimeout(()=>{
  6. const button = document.createElement('button')
  7. button.textContent= 'click 1'
  8. div1.appendChild(button)
  9. },1000)
  10. div1.addEventListener('click', (e)=>{
  11. const t = e.target
  12. if(t.tagName.toLowerCase() === 'button'){
  13. console.log('button'被点击了)
  14. }
  15. })

3.自定义事件

浏览器自带事件一共100多种事件,列表在 MDN上,除此之外开发者还能自定义事件
代码如下:http://js.jirengu.com/tuhonowiga/1/edit?html,js,output

  1. //html代码
  2. <div id=div1>
  3. <button id=button1>点击触发 frank 事件
  4. </button>
  5. </div>
  6. //JS代码
  7. button1.addEventListener('click', ()=>{
  8. const event = new CustomEvent("frank", {"detail":{name:'frank', age: 18}})
  9. button1.dispatchEvent(event)
  10. })
  11. button1.addEventListener('frank', (e)=>{
  12. console.log('frank')
  13. console.log(e)
  14. })