面试题 - DOM精选

51 阅读1分钟

简述DOM事件模型

先经历从上到下的捕获阶段,再经历从下到上的冒泡阶段。 使用方法如:

addEventListener('click', fn, true/false) // 第三个参数是useCapture,第三个参数也可以用对象的写法

阻止捕获或冒泡的方法:

event.stopPropagation()

手写事件委托

面试常见写法:

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

这种写法有bug,如果点击的是li里的span,则不会触发fn()

事件委托的好处:

  1. 节省监听器
  2. 实现动态监听

事件委托的坏处:

  1. 在调试时比较复杂,不容易确定监听者都有谁(擅用chrome的eventlistener)

手写可拖拽div

let dragging = false;
let position = [];

const draggable_div = document.getElementById("draggable_div");

draggable_div.addEventListener("mousedown", function (e) {
    dragging = true;
    position = [e.clientX, e.clientY];
});

document.addEventListener("mousemove", function (e) {

    if (!dragging) return;

    const x = e.clientX;
    const y = e.clientY;

    const deltaX = x - position[0];
    const deltaY = y - position[1];

    const left = parseInt(draggable_div.style.left || 0, 10);
    const top = parseInt(draggable_div.style.top || 0, 10);

    draggable_div.style.left = left + deltaX + "px";
    draggable_div.style.top = top + deltaY + "px";

    position = [x, y];

});


document.addEventListener("mouseup", function () {
    dragging = false;
});

要点:

  1. 注意监听范围,不能只监听div
  2. drag事件很难用,别用
  3. 使用transform会比top/left性能更好(因为可以避免reflow和repaint)