js事件拓展

事件总括

    *   1、行为本身:浏览器天生就赋予其行为onclick onmouseover onmouseout (onmouseenter onmouseleave不会产生事件冒泡)  onmousemove
    *   onmousedown onmouseup onmousewheel onscroll onresize onload onunload onfocus onblur onkeydown onkeyup。。。
    *   没有给上述行为绑定方法,事件也存在,触发后执行,只是什么都不做而已
    *   2、事件绑定:
    *       oDiv.onclick=function...     DOM0级事件绑定  onclick行为定义在oDiv的私有属性上
    *       oDiv.addEventListener('click',function(){},false)  DOM2级事件 addEventListener这个属性是定义在EventTarget
    *       这个类的原型上

事件的传播机制

    * 捕获阶段:从里往外一次查找元素
    * 目标阶段:当前事件源本身操作
    * 冒泡阶段:从内到外依次触发相关行为(最常用)
事件传播机制.jpg
  • 冒泡和捕获
    捕获就是:爹(target)的事件触发,儿子和孙子的相同的事件也会被触发
    冒泡就是:儿子(target)触发事件,爹和祖宗的相同的事件也会被触发
    阻止冒泡

e.stopPropagation会阻止冒泡,意思就是到我为止,我的爹和祖宗的事件就不要触发了。

事件委托

把事件绑定到目标元素群的父元素上,通过e.target来判断点击的真正目标,在执行相应的程序

事件冒泡与默认行为

让事件处理函数return false来阻止冒泡和默认行为, 可以认为return false做了三件事情:
1.stopPropagation();
2.preventDefault();
3.立即结束当前函数并返回。

DOM 0级事件

  • 给元素对象的某一个私有的属性赋一个值(一个函数的值),当事件触发的时候找到对应的属性值,并且执行
  • DOM 0级事件只能给元素的某一个事件绑定一次方法,最后绑定的方法会把前面绑定的所有的方法都覆盖掉

DOM 2级事件

  • 给当前元素的某一个事件绑定的方法都放置在事件池中,当事件执行的时候,会把事件池里的所有的方法依次去执行
    1.addEventListener 绑定事件
    2.removeEventListener 移除事件
  • DOM 2级事件可以为当前元素的某一个事件绑定多个不同的方法,当前事件触发时,会到对应的事件池中把所有的绑定的方法依次执行。
  • DOM2和DOM0事件共存,不会冲突 。
深入
  • DOM2可以给元素的某一个事件行为绑定多个方法
    1.事件触发时执行对应的方法们,此时不管哪个方法中的this指向的都是当前元素
    2.我们按顺序把顺序增加到‘事件池’中,当触发事件时,方法按照添加的顺序依次执行
    3.如果当前的方法已经给元素的这个行为绑定过一次了,事件池中这个方法不会重复添加
  • DOM2中,我们一般绑定的都是实名函数,只有这样,当移除的时候才知道移除谁,
    在IE6-8中绑定的方法只能在冒泡阶段发生。
  • DOM2事件在IE6-8中兼容问题。
    1.绑定的语法不一样,IE6-8中,使用attachEvent、detachEvent
    2.标准浏览器this指向当前元素,IE6-8指向window
    3.重复绑定问题,IE6-8 相同的方法可以重复绑定
    4.顺序问题,标准浏览器按绑定的顺序执行函数,IE6-8 没有顺序
function on(ele,type,fn){
  if(/^self/.test(type)){//说明是自定义的事件   都带前缀self
    if(!ele['aself'+type]){
      ele['aself'+type]=[]//创建自定义事件的事件池
    }
    var a=ele['aself'+type];
    for(var i=0;i<a.length;i++){
      if(a[i]==fn)return;
    }
      a.push(fn);//如果这个函数没有添加过事件池,那么就添加进去
  }else if(ele.addEventListener){//标准浏览器的事件添加
    ele.addEventListener(type,fn,false);
  }else{//IE浏览器的事件添加
    if(!ele['aEvent'+type]){
      ele['aEvent'+type]=[];
    }
    var a=ele['aEvent'+type];
    for(var i=0;i< a.length;i++){
       if(a[i]==fn)return;
       ele.attach('on'+type,function(){//提前绑定好事件,只要触发就执行run
          run.call(ele);
       })
    }
    a.push(fn);
  }
}
function run (){
  var e=e||window.event;
  if(!e.target){
    e.target=e.srcElement;
    e.pageX=e.clientX+(document.documentElement.scrollLeft||document.body.scrollLeft);
e.pageY= e.clientY+(document.documentElement.scrollTop||document.body.scrollTop)
  }
    e.stopPropagation=function(){
      e.cancelBubble=true;
    }
    e.preventDefault=function(){
      e.returnValue=false
    }
    var a= this['aEvent'+type];
    if(a){
      for(var i=0;i< a.length;i++){
        var fn=a[i];
        if(type fn == 'function'){
          fn.call(this,e);
        }else{
          a.splice(i,1)
          i--;
      }
    }
  }
}
function selfRun(selfType,e){
        var a=this['aSelf'+selfType];
        if(a){
            for(var i=0;i< a.length;i++){
                var fn=a[i];
                if(type fn == 'function'){
                    fn.call(this,e);
                }else{
                    a.splice(i,1)
                    i--;
                }
            }
        }
    }
function off(ele,type,fn){
        if(/^self/.test(type)){
            var a=ele['aSelf'+type];
            if(a){
                for(var i=0;i< a.length;i++){
                    if(a[i]==fn){
                        a[i]=null;
                        return;
                    }
                }
            }
        }
        if(ele.removeEventListener){
            ele.removeEventListener(type,fn,false);
        }else{
            var a=ele['aEvent'+type]
            if(a){
                for(var i=0;i< a.length;i++){
                    if(a[i]==fn){
                        a[i]=null;
                        return;
                    }
                }
            }
        }
    }

自定义事件(订阅发布模式)

function EventEmitter(){
}
EventEmitter.prototype.on=function(type,fn){
  if(!this['aEmitter'+type]){
    this['aEmitter'+type]=[]
  }
  var a=this['aEmitter'+type];
  for(var i=0i<a.length;i++){
    if(a[i]==fn)return;
    a.push(fn);
  }
}
EventEmitter.prototype.run=function(type,e){
  var a=this['aEmitter'+type];
  if(a){
    for(var i=0i<a.length;i++){
      if(typeof a[i]=='function'){
        a[i].call(this,e);
      }else{
        a.split(i,1);
        i--;
      };
    }
  }
}
EventEmitter.prototype.off=function(type,fn){
  var a=this['aEmitter'+type];
  if(a){
    for(var i=0i<a.length;i++){
      if(a[i]==fn){
        a[i]=null;
      };
    }
  }
}

jquery绑定

$(ele).bind() ------在新版本已经淘汰
  • 将会给所有匹配的元素都绑定一次事件,当元素很多时性能会变差。 而且后来动态新增的元素不会被绑定

  • 可以添加自定义事件 然后用trigger来手动触发该事件。

  • 多个事件类型可以通过用空格隔开一次性绑定:

$('#foo').bind('mouseenter mouseleave', function() {
  $(this).toggleClass('entered');
});
  • 可以通过传递一个事件类型/处理函数的数据键值对映射来绑定多个事件处理程序
$('#foo').bind({
  click: function() {
    // do something on click
  },
  mouseenter: function() {
    // do something on mouseenter
  }
});
$(ele).delegate()
  • 它将事件处理函数绑定在指定的根元素上, 由于事件会冒泡,它用来处理指定的子元素上的事件。
  • 用于事件委托
$("table").delegate("td", "click", function() {
  $(this).toggleClass("chosen");
});

是等价于下面使用.on()的代码:

$("table").on("click", "td", function() {
  $(this).toggleClass("chosen");
});
$(ele).on()
  • 绑定事件最通用的方法,用$(ele).off()解绑事件
  • 向事件处理函数中传入数据,并且在事件处理函数中通过名字来获取传入的数据:
function myHandler(event) {
  alert(event.data.foo);
}
$("p").on("click", {foo: "bar"}, myHandler)
$(ele).one()
  • 处理函数在每个元素上每种事件类型最多执行一次
$( "#foo" ).one( "click", function() {
  alert( "这个函数只会执行一次" );
});
  • 如果该方法的第一个参数包含多个用空格分隔的事件类型的话,那么每种类型的事件被触发时,处理函数仅会被每个事件类型调用一次。
$( "#foo" ).one( "click mouseover", function( event ) {
  alert( "The " + event.type + " event happened!" );
});
$(ele).trigger()
  • 用来触发事件
$('#foo').on('click', function() {
      alert($(this).text());
    });
 $('#foo').trigger('click');//相当于用户点击了该元素
  • 若要触发通过 jQuery 绑定的事件处理函数,而不触发原生的事件,使用.triggerHandler() 来代替。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容

  • 什么是事件: 我们可以简单的把事件理解为浏览器的感知系统。比如说:他可以感觉到用户是否点击(click)了页面、鼠...
    张松1366阅读 6,788评论 1 6
  • 总结: 鼠标事件 1.click与dbclick事件$ele.click()$ele.click(handler(...
    阿r阿r阅读 1,603评论 2 10
  • 第1章 鼠标事件 1-1 jQuery鼠标事件之click与dbclick事件 用交互操作中,最简单直接的操作就是...
    mo默22阅读 1,275评论 0 6
  • 天上飘着细雨 水面漾着涟漪 走在水镇的小路上 我遇见了你 你的眼睛望着天 你的心中可下着雨 你用手心接雨滴 你的心...
    大毛愣星阅读 501评论 0 0
  • 《管理的常识》拆书分享-听听管理咨询菜鸟谈管理(二) 第二部分:对绩效负责的管理观 1) 管理只对绩效负责 ...
    浅浅的夕阳阅读 689评论 0 2