js事件流

js事件流

事件冒泡

从最具体的元素开始一层层向上传递,就是从元素本身一直到body>html>document>window(远古ie8直到document);

事件捕获

从最不具体的元素开始一层层向下传递,同样是从window>document>html>body>element(远古ie不再支持)

为了兼容这两种方式,w3c规定事件是先从window捕获到元素,然后再冒泡到window,在此需要说下

dom事件的分类

dom 0级事件

主要有两种格式:写在标签里的onclick事件以及ele.onclick = function(){},这种情况下,事件只发生冒泡的阶段

dom 2级事件

主要就监听和移除事件,addEventListener()和removeEventListener()。

它们都有三个参数:第一个参数是事件名称,第二个是事件函数,第三个boolean为true则是捕获,否则是冒泡。

这里又要多一句,在dom2级中规定的是实际发生事件的元素在捕获阶段不能接收到事件。也就是说捕获阶段是没有发生元素事件的,只有冒泡过程中才会触发。如下

然而在浏览器的实现上,都是冒泡与捕获均能触发事件。

添加事件

var addEvent = function( obj, type, fn ) {
  if (obj.addEventListener)
      obj.addEventListener( type, fn, false );
  else if (obj.attachEvent) {//这个是兼容ie7,ie8
      obj["e"+type+fn] = fn;
      obj.attachEvent( "on"+type, function() {
          obj["e"+type+fn].call(obj, window.event);
      } );
  }
};

移除事件

var removeEvent = function( obj, type, fn ) {
  if (obj.removeEventListener)
      obj.removeEventListener( type, fn, false );
  else if (obj.detachEvent) {
      obj.detachEvent(  "on" +type, obj["e"+type+fn] );
      obj["e"+type+fn] = null;
  }
};

阻止事件(冒泡以及默认行为)

var stopEvent = function(e){
    e = e || window.event;
    if(e.preventDefault) {
      e.preventDefault();//阻止默认事件
      e.stopPropagation();//阻止冒泡
    }else{
      e.returnValue = false;
      e.cancelBubble = true;
    }
}

获取事件源对象

var getEventTarget = function(e){
   e = e || window.event;
  var target = event.srcElement ? event.srcElement : event.target;
  return target;
}

绑定onpropertychange事件

onpropertychange,它在一个元素的属性发生变化的时候触发,一般用在表单元素中捕获其value值改变,它比onchange事件更实时捕获它的改变,不过为微软私有事件。FF大致和它相似的有oninput事件,不过它只针对textfield与textarea的value属性。safari,firefox,chrome与 opera都支持此事件。

 var addPropertyChangeEvent = function (obj,fn) {
  if(window.ActiveXObject){
      obj.onpropertychange = fn;
  }else{
      obj.addEventListener("input",fn,false);
  }
}

点击空白处关闭

$(document).click(function(e) {
    function autoHide(i) {
        this.e = e;
        var con = $(i);
        if (!con.is(e.target) && con.has(e.target).length === 0) {
            con.addClass('hidden');
        }
    }
    autoHide(ele)
}

这个也会有些问题,例如我要实现一个自定义省份选择菜单

添加了这个元素以后,并且给这个输入框添加事件后,点击会发现下拉框没有显示,是因为,输入框也是下拉框的元素之外,点击会让它隐藏,那么就需要在点击输入框后阻止接下来的事件。

$('body').on('click', ' .select-choose', function() {
    $(this).next('.select-open').toggleClass('hidden');
    return false;//阻止事件冒泡,也阻止了事件
    //event.stopPropagation();//只阻止事件冒泡
});

return false和stopPropagation()

return false也是一种让a标签失效的办法,并且会阻止事件本身,而stopPropagation是js原生的效果,且不会阻止事件本身,举个栗子

在某写情况下需要让a标签失效的时候,主要用href="#" href="javascript:void(0)",以及onclick="return false"。

<a href="https://www.baidu.com" id="lnktoBaidu">1231231</a>
$('#lnktoBaidu').click(function(e){
    e.stopPropagation(); //跳转到baidu
    // return false; //原页面不跳转
})

这个return false有点像上面阻止事件的写法

e.preventDefault();//阻止默认事件
e.stopPropagation();//阻止冒泡
rerturn '';//终止函数,返回,代表之后的回调都不会执行了。

这就是return false的机制了。

事件委托

下面再顺便说下事件委托的机制,常见的,例如一个ul下某个li变化

ul.onmouseover = function(e){
  var e = e || window.event;
  var target = e.target || e.srcElement;
  if(target.nodeName == "LI"){
    target.style.background = "red";
  }
}

本质上就是在父元素上绑定事件,在子元素触发某些条件的时候改变,那么就不要在每个子元素上绑定事件,大大提高了效率不说,而且还能应对添加某些元素后的事件响应

改天可以说说event,这个也很能讲讲。

posted @ 2017-04-26 11:31  慕迪亚  阅读(173)  评论(0编辑  收藏  举报
你的浏览器不支持canvas