事件流 - 事件传播

653 阅读3分钟

事件流 - 事件传播

事件监听:

  1. addEventListener('事件名不带 on',function,false/true);
  • 注意:标准浏览器。事件名不带 on,有第三个参数,true 为捕获,false 为冒泡(默认) 2. attachEvent('事件名带 on',function)
  • ie678,;事件名带 on,没有第三个参数(因为 ie678 不支持捕获) - 标准浏览器:addEventListener 是谁先绑定 谁先执行;
  • ie678 : attachEvent 是谁先绑定 谁后执行

事件流模型是什么?

  • 事件冒泡:根据 DOM 树,从下往上传播;
  • 事件捕获:根据 DOM 树,从上往传播;

事件传播的三个阶段: 捕获-1, 目标-2, 冒泡-3

  • 事件冒泡: 事件的一种传播方法,根据 DOM 树从下往上传播;
  • 事件捕获: 事件的一种传播方法,根据 DOM 树从上往下传播;不支持 IE678;
  • 目标: 点击的事件所属的事件源;

DOM 事件流是什么?

  • :捕获阶段 -> 目标阶段 -> 冒泡阶段

描述 DOM 事件捕获的具体流程

window --> document --> documentElement(html 标签) --> body --> .... --> 目标对象

Event 对象常见应用

+ event.preventDefault(),阻止默认行为 
+ +event.stopPropagation(),阻止事件冒泡 
+ event.target,事件的引发者
+ 还有一些 获取 坐标的 eg:
    - e.pageX/Y 鼠标位于整个页面 的坐标 
    - e.offsetX/Y 鼠标位于距离定位盒子的左上距离 案例: 放大镜,拖拽,滚动条等;

对事件流的理解

1. 事件的绑定、解绑
a.事件绑定普通方法... 容易出现事件层叠;
b.所以一般原生 js 为我们提供了一个事件监听的方法 addEventListener();
ie678 不支持,attachEvent(); 这个需要封装 2. 事件对象
a.事件被触发的时候有一个事件对象 event,(兼容不好得封装); b.他里面有很多的属性和方法:pageY/X; 鼠标位于整个页面中的坐标; c.放大镜/拖拽/滚动...
3. a.事件是可以传播的,他的阶段有三个捕获-目标-冒泡; b.target:事件引发者; eventPhase: 看元素处于哪个阶段;
c. 事件冒泡:根据 DOM 树,从下往上传播;
d. 事件捕获:根据 DOM 树,从上往下传播; c.事件传播可以阻止;
d.主动使用冒泡,就是事件委托... e.利用冒泡为子元素绑定事件,新创建的子元素也会有老事件;

事件委托参考

<div class="box">
    <p class="child"></p>
</div>
.box {
  width: 300px;
  height: 300px;
  margin: 200px;
  cursor: pointer;
  border: 1px solid #ccc;
  background-color: skyblue;
}
.child {
  width: 100px;
  height: 100px;
  margin: 100px;
  cursor: move;
  border: 1px solid #ccc;
  background-color: lightgreen;
}
let box1 = document.querySelector('.box')
let box2 = document.querySelector('.child')

冒泡

document.addEventListener('click', () => {
  console.log('您点击了 document');
})

box1.addEventListener('click', () => {
  console.log('您点击了 box1');
  // 您点击了 box1
  // 您点击了 document
})

box2.addEventListener('click', () => {
  console.log('您点击了 box2');
  // 您点击了 box2
  // 您点击了 box1
  // 您点击了 document
})

判断阶段 (捕获-1,目标-2,冒泡-3)

document.addEventListener('click', (event) => {
  console.log('document:' + event.eventPhase);
}, true)

box1.addEventListener('click', (event) => {
  console.log('box1:' + event.eventPhase);
})

box2.addEventListener('click', (event) => {
  console.log('box2:' + event.eventPhase);
  // document:1 捕获
  // box2:2 目标
  // box1:3 冒泡
})

事件引发者

document.addEventListener('click', (event) => {
  console.log('document:' + event.target.tagName);
}, true)
// document:BODY

box1.addEventListener('click', (event) => {
  // console.log('box1:' + event.target.tagName);
}, true)
// document:DIV

box2.addEventListener('click', (event) => {
  // console.log('box2:' + event.target.tagName);
}, true)
// document:P

阻止冒泡

  • event.stopPropagation()    // 正常浏览器
  • event.cancelBubble = true   // IE678
    document.addEventListener("click",function(){
        console.log("您点击了document");
    });

    box1.addEventListener("click",function(){
        console.log("您点击了box1");

    });

    box2.addEventListener("click",function(event){
        var event = event || window.event;
        console.log("您点击了box2");
        //  阻止冒泡
        if(event.stopPropagation) {
            event.stopPropagation();  // 正常浏览器
        }else {
            event.cancelBubble = true;  //  ie678
        }
    });