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

事件委托

假如我们希望实现一个功能,希望我点击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

推荐阅读更多精彩内容

  • 前端开发面试题 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。 题目类型: 理论知...
    WhaleFall_丶阅读 1,236评论 0 5
  • 请参看我github中的wiki,不定期更新。https://github.com/ivonzhang/Front...
    zhangivon阅读 3,542评论 2 17
  • 一:认识jquery jquery是javascript的类库,具有轻量级,完善的文档,丰富的插件支持,完善的Aj...
    xuguibin阅读 492评论 1 6
  • 事件委托(Event Delegation)是JS中一项十分重要的应用,使用事件委托可以避免对每一个节点添加监听器...
    李悦之阅读 68评论 0 0
  • HTML 5 HTML5概述 因特网上的信息是以网页的形式展示给用户的,因此网页是网络信息传递的载体。网页文件是用...
    阿啊阿吖丁阅读 911评论 0 0