DOM事件与事件委托

198 阅读2分钟

DOM事件分为DOM事件模型与事件机制

DOM 事件模型

DOM事件模型分为捕获和冒泡。一个事件发生后,会在子元素和父元素之间传播,这种传播分为三个阶段。

  • 捕获阶段:事件从window对象自上而下向目标节点传播
  • 目标阶段:目标节点处理事件
  • 冒泡阶段:事件从目标节点自下而上向window对象传播

事件机制

点击事件:进行事件监听,比如爷父子三代中包含文字,点击文字触发监听,都会触发

触发的调用顺序:网景为爷父子,IE为子父爷,有监听便调用,并提供事件信息

事件捕获:从外向内找监听函数 document.documentElement得HTML标签和document.body得body标签

事件冒泡:从内向外找监听函数

开发者自己选择放在捕获阶段还是冒泡阶段

事件委托

简述事件委托

关键:检查事件是否来自你所预期的元素。

优点

可以大量节省内存占用,减少事件注册 可以实现当新增子对象时无需再次修改其绑定事件,对于动态内容部分尤为合适

代码实现

场景一:100个按钮,通过监听他的一个父元素即可

(监听100个元素的祖先,待冒泡时再判断target是否为这些按钮之一)

div1.addEventListener(
'click', (e) => {
  const t = e.target
  //标签的小写名称
  if(t.tagName.toLowerCase() === 'button') {
  console.log(t.innerText)
  console.log(t.dataset.id)
}
})

先判断t.tagName是不是button

t.innerText是按钮内的内容,dataset.id是按钮的id

场景二:监听目前不存在的元素的点击事件

(监听祖先,待点击时看是否为要监听的元素)

先创造按钮,在按钮里加内容,将按钮加到div里,添加div的监听事件,并判断是否为button,t.tagName.toLowerCase() === 'button'

setTimeout(() => {
  const button = document.createElement('button')
  button.innerText = 'click 1'
  div1.appendChild(button)
}, 1000)

div1.addEventListener('click', (e) => {
  const t = e.target
  if (t.tagName.toLowerCase() === 'button') {
    console.log(t.innerText)
  }
})

如何实现事件委托

我们来实现上例中父层元素 #list 下的 li 元素的事件委托到它的父层元素上

// 给父层元素绑定事件
document.getElementById('list').addEventListener('click', function (e) {
  // 兼容性处理
  var event = e || window.event;
  var target = event.target || event.srcElement;
  // 判断是否匹配目标元素
  if (target.nodeName.toLocaleLowerCase === 'li') {
    console.log('the content is: ', target.innerHTML);
  }
});

封装事件委托

setTimeout(() => {
  const button = document.createElement('button')
  button.innerText = 'click 1'
  div1.appendChild(button)
}, 1000)


function on(eventType,element,selector,fn){
  if(!(element instanceof Element)){
    element=document.querySelector(element)
  }
  element.addEventListener(eventType,(e)=>{
    const t=e.target
    if(t.matches(selector)){
      fn(e)
    }
  })
}

on('click','#div1','button',()=>{
  console.log('button被点击了')
})

知识点:

if(!(element instanceof Element)){
    element=document.querySelector(element)
}

//匹配选择器
t.matches(selector)

事件委托

给一个元素添加一个监听,看他的target是否满足Selector,满足就执行函数,否则就放过,其实这不是最完整的,还需要优化递归父亲

问:JS支持事件不?

不支持,这里的事件是DOM事件,是浏览器的功能,js只是调用了DOM提供的addEventListener这个API,那么如何手写JS事件…