简述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()
事件委托的好处:
- 节省监听器
- 实现动态监听
事件委托的坏处:
- 在调试时比较复杂,不容易确定监听者都有谁(擅用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;
});
要点:
- 注意监听范围,不能只监听div
- drag事件很难用,别用
- 使用transform会比top/left性能更好(因为可以避免reflow和repaint)