DOM 必考题

1、请简述DOM事件模型

  • 什么是DOM事件模型:每一个事件都会先经历从上到下的捕获阶段,再经历从下到上的冒泡阶段。
  • 如何选择捕获or冒泡:添加事件监听时候addEventListener(’click’,fn,true/false) 第三个参数可以选择阶段。
    true表示把它放到捕获阶段,false或者不传把它放到冒泡阶段。
  • 在这两个阶段希望停止传播(捕获/冒泡到一个div就不要往下走了)
    可以使用 event.stopPropagation() 来阻止捕获或冒泡。

2、手写事件委托

BUG版(正确答案)

思路:
当用户点击列表时,他点击的目标e.target,的标签名tagName,小写之后是li(默认大写)
如果是li那就说明它点击列表中的某一项,就执行某个函数。

事件委托就是,我不监听li我监听li的爸爸。只要点击li就会触发函数。

我们在使用target的时候是用e.target 还是 e.currentTarge?
两者区别:
currentTarge是我监听的对象,比如说我监听ul,那就是ul
target是用户触发的对象,它点span那就是span它点li就是li

 ul.addEventListener('click', function(e){
     if(e.target.tagName.toLowerCase() === 'li'){
         fn()// 执行某个函数
     }
 })

bug 在于,如果用户点击的是 li 里面的 span,就没法触发 fn,这显然不对。

bug就bug吧工作中不用自己写,Vue/React中自动帮你事件委托了。

高级无BUG版本

思路:当你点击span后,递归遍历span的祖先元素找li 最多看到ul.

function delegate(elemet,eventType,selector,fn){
  element.addEventListener(eventType,e=>{
    let el = e.target
    while(!el.matches(selector)){//el.matches(selector)判断你点击的元素是不是li
      if(element === el){  //如果我找到的元素等于ul了 ,那说明没找到li那就置为空
       el = null
       break
      }
       el = el.parentNode //让你等于你爸爸,再循环看看你是不是li
    }
    //跳出循环后如果el空那就什么都不做,否则执行fn此时fn的this是el
    el && fn.call(el,e) 
  })
  return element
}

delegate(ul,'click',li,f1)
只要你点击了ul中的li(无论是li自身还是li后代)执行fl.

事件委托的好处与坏处
好处:
1、节省监听器
2、动态监听
坏处:
调试比较复杂,不容易确定当前元素有哪些事件监听。可能点击一个div触发莫名其妙的事件,因为点击的div可能有n多父元素,不可能一层一层的找。

https://www.jianshu.com/p/d94dc9be547e

3、手写可拖拽div

  • mousedown 事件在指针设备按钮按下时触发。
  • 当指针在元素中时, mouseup事件在指针设备(如鼠标或触摸板)按钮放开时触发。
  • 当指针设备 ( 通常指鼠标 ) 在元素上移动时,mousemove 事件被触发。
  • clientX 事件属性返回当事件被触发时鼠标指针相对于浏览器页面(或客户区)的水平坐标。
  • parseInt 解析一个字符串返回一个整数。
  • 代码
    JS Bin - 手写拖拽div
  • 思路:我鼠标按下div的时候记录初始坐标,当我移动的时候做差然后对div进行移动。移动完了记录基准点。
  • 要点
    1、注意监听范围,不能只监听div
    mousedown是监听div其他放在document上
    因为如果都放在div上大幅度移动容易掉,超出div且只监听div
    2、使用transfrom 比top/left性能更好避免reflow和repaint
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容