JavaScript事件机制

2019-03-12  本文已影响0人  椰果粒

概念

1、事件:点击事件,鼠标移入移出事件等。通常与函数配合,当发生这个事件时,会触发函数。
2、DOM事件流:事件捕获和事件冒泡
      DOM模型是一个树型的结构,HTML元素是有层次的。
      当HTML上的某个元素产生一个事件时,这个事件就会在DOM树中按照一定的顺序传播,途中所经过的各个节点都会接收到该事件。这个传播的过程就是DOM事件流。
3、DOM事件模型:事件捕获,处于目标阶段,事件冒泡
4、冒泡事件流:
  默认情况下,事件使用的是冒泡事件流。当某个元素被触发时,这个事件就会沿着该节点的各个父节点一直冒泡,在各个阶段都可以终止冒泡。如果不在途中停止冒泡,就会一直冒泡到文档的根部。
5、捕获事件流:
  和冒泡相反,在捕获事件流中,事件的处理是从根部开始的,事件会从这个元素最祖先的元素一直往下传递。
6、DOM标准事件流模型:
  DOM标准事件流同时支持事件冒泡和事件捕获。
  先捕获
  捕获和冒泡都会触发所有对象,从document开始,再到document结束。
  window->document->body->div->button->div->body->document->window
7、事件传导的三个阶段:
  1、事件捕获:事件会沿着目标元素的祖先元素向下传递,经过目标节点的每一个祖先节点,一直到目标节点。
      看看有没有设置成捕获阶段的,addEventListener(,,true),如果有就先触发了,不用管冒泡(false)的那些
  2、处于目标阶段:事件传到到目标元素,浏览器查找到指定给目标元素的监听器,就会执行该监听器。
      目标元素触发
  3、事件冒泡:事件沿着DOM树向上传送,直到document节点,浏览器会检测监听器(捕获阶段的就不看了)并执行。
      看看设置成冒泡的,addEventListener(,, false),一层层向上触发,这时候不用管捕获(true)的那些了

  先捕获,捕获到事件源之后通过事件传播进行事件冒泡。
  IE10以下不支持捕获,所以就少了这个阶段。

8、两个用于事件绑定的方法
  1、addEventListener(event, listener, useCapture)
    event:事件名称,比如click,没有on
    listener:监听函数
    useCapture:是否使用事件捕获进行事件捕捉,默认false,默认用的是事件冒泡
  2、attachEvent(event, listener),主要用于IE10以下的
    event:事件名称,比如onclick
    listener:监听函数
9、阻止
  1、阻止事件冒泡:event.stopPropagation()
  2、阻止默认事件:event.preventDefault()


10、事件委托:一个事件本来要绑定到某个元素上,但是给它绑定到了父元素(祖先元素)上,利用事件冒泡原理,触发执行
    事件委托在jQuery中的表现: $(document).on("click", function(){})这种的。一般用于动态生成的元素。

11、事件委托的例子
    1、通过parent元素给children元素注册click事件
    2、新添加的元素也有事件
    3、获取点击元素的下标

12、事件委托的好处
    1、提高网页性能
        本来要对所有li都添加点击事件,现在只需要给Ul添加一个点击事件。减少了DOM操作。
    2、通过事件委托添加的事件,对于后来添加上的元素同样有效
        如何解释:比如有个ul,里面有两个li,通过循环给每个li添加点击事件,这两个li都可以触发事件。这时候我们通过append在ul里面再添加两个li,发先也能点击并触发事件。

示例:

var wrapper = document.getElementsByClassName('wrapper')[0];
var content = document.getElementsByClassName('content')[0];
var inner = document.getElementsByClassName('inner')[0];

wrapper.onclick = function(){
    console.log("wrapperBubble");
}
content.onclick = function(){
    console.log('contentBubble');
}
inner.onclick = function(){
    console.log("innerBubble")
}

wrapper.addEventListener('click',function(){
    console.log("wrapper");
},true);
content.addEventListener('click',function(){
    console.log("content");
},true);
inner.addEventListener('click',function(){
    console.log("innerBuhuo");
},true);

先捕获,后冒泡,作用于它自己身上的,就直接先点击哪个是哪个
事件执行的顺序符合谁先绑定谁先执行

并不是所有的事件都冒泡
不冒泡的:focus,blur,change,submit,reset,select等

封装阻止冒泡的方法

function stopBubble(e){
    if(e.stopPropagation){
        e.stopPropagation();
    }else{
        e.cancelBubble = true;
    }
}

不冒泡的事件:

focus,blur,change,submit,reset,select等

ul里的li不固定,输出li里面的内容,用事件委托的方式

var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function(e){
    var e = e || window.event;
    var target = e.target || e.srcElement;
    e.stopPropagation();
    console.log(target.innerText);
}

事件委托的优点:
1、性能高,不需要循环
2、灵活,可以有很多li

综合示例:

<style>
  #parent{
    width: 200px;
    height: 200px;
    background-color: red;
  }
  #child{
    width: 100px;
    height: 100px;
    background-color: green;
  }
</style>
<div id="parent">
  父元素
  <div id="child">子元素</div>
</div>


<ul>
  <li>click me</li>
  <li>click me</li>
  <li>click me</li>
  <li>click me</li>
  <li>click me</li>
</ul>

// 1、 通过parent元素给children元素注册click事件
var parent = document.getElementById("parent")
var child = document.getElementById("child")

// 我给父元素添加了点击事件,当我点击子元素的时候,同样也能触发
parent.onclick = function(e){
  if(e.target.id === "child"){
    console.log("click child")
  }
}

// 2、对新添加的元素也有事件
var ul = document.querySelector("ul");  // querySelector仅仅返回第一个符合的元素。
var lis = document.getElementsByTagName("li")
ul.onclick = function(e){
  var e = e || window.event
  var target = e.target || e.srcElement
  if(target.nodeName.toLowerCase() === "li"){
    console.log("this is li element")
  }
}
// 这时候,我们添加几个元素
var li = document.createElement("li")
li.innerHTML = "new click!"
ul.appendChild(li)
// 被添加的元素也有点击事件。


// 3.1、获取点击元素的下标
for(let i=0; i<lis.length; i++){
  lis[i].onclick = function(){
    console.log(i);
  }
}
// 3.2、或者,把i变成li的属性
for(var i=0; i<lis.length; i++){
  lis[i].index = i;
  lis[i].onclick = function(){
    console.log(this.index)
  }
}
// 3.3、声明一个立即执行函数
for(var i=0; i< lis.length; i++){
  lis[i].onclick = (function(n){
    return function(){
      console.log(n)
    }
  })(i)
}
上一篇 下一篇

猜你喜欢

热点阅读