事件冒泡(事件委托),拖拽事件

事件委托

假如我们希望实现一个功能,希望我点击ul中的li元素让它执行某个函数,应该怎么写?

ul.addEventListener('click',function(e){
      if(e.target.toLowerCase()==='li'){
            fn()
      }
   })

这样写是有明显的bug的,如果用户点击的是 li 里面的 span,就没法触发 fn,这显然不对。所以如果li有span的话,我们就需要判断span的父元素中有没有li,如果有的才会执行函数,如果没有就不执行函数。
所以应该这样写,这样写的思路在于,如果,我点击的li中是有其他元素(span)的,那么只要它是我希望点击元素(span)的子元素,函数就会执行。所以我们要递归的去找到当前点击元素的父元素,当父元素是是我们要点击的元素(li)时执行fn。如果一值到头(ul)都找不到,那么说明(ul)中没有(li)那么函数就不会执行。


ul.addEventListener('click',function(e){
    // 获取当前元素,这个元素可能是li,也可能不是
    let e1 = e.target
   // 当这个元素不是li的时候 
    while(!e1.matches(li)){
           if(ul === e1){
                e1 = null
                break
          }
         //遍历它的父元素
         e1 = e1.parentNode
       }
    // 直到e1的父元素是li时才执行
    e1 && fn()
 })

下面是事件冒泡的同用版本

 function delegate(element, eventType, selector, fn) {
     element.addEventListener(eventType, e => {
       let el = e.target
       while (!el.matches(selector)) {
         if (element === el) {
           el = null
           break
         }
         el = el.parentNode
       }
       el && fn.call(el, e, el)
     })
     return element
   }

拖拽事件

var dragging = false
var position = null

xxx.addEventListener('mousedown',function(e){
  dragging = true
  // 记录刚开始拖拽时候的位置
  position = [e.clientX, e.clientY]
})


document.addEventListener('mousemove', function(e){
  if(dragging === false){return}
  const x = e.clientX
  const y = e.clientY
  const deltaX = x - position[0]
  const deltaY = y - position[1]
  const left = parseInt(xxx.style.left || 0)
  const top = parseInt(xxx.style.top || 0)
  xxx.style.left = left + deltaX + 'px'
  xxx.style.top = top + deltaY + 'px'
  //更新这个位置
  position = [x, y]
})
document.addEventListener('mouseup', function(e){
  dragging = false
})

这里要注意的地方有下面几点
1.监听的不是div而是document,不然移动快了的话,可能会掉
2.设置style的时候要加上px,获取的鼠标的坐标也要先转换成数字
3.一开始的时候style还没有top和left,所以如果没有先设为0

你可能感兴趣的:(事件冒泡(事件委托),拖拽事件)