js的事件流

一、JavaScript的事件对象

1.event:事件对象;

当一个事件发生时,和当前这个对象发生的事件有关的信息就会临时保存在一个指定的地方----event对象,供我们需要的时候调用。

2.注意:

事件对象必须在一个事件调用函数中使用时才有内容。函数是不是事件函数,不是定义的时候决定,而是调用的时候决定。

        function fn(){alert(event);}
        fn;                         //直接调用没有内容
        document.onclick = fn;      //事件调用有内容
3.兼容写法:
         var ev = ev || event;

例1:我们可以使用兼容写法查看浏览器中event中的属性和方法;

        document.onclick = function(ev){
            var ev = ev || event;
            for (var attr in ev){
                console.log(ev[attr]);
            }
        }

例2:获取鼠标位置;

        document.onclick = function(ev){
            var ev = ev || event;
            var oLeft = ev.clientX;
            var oTop = ev.clientY;
            console.log(oLeft);
            console.log(oTop);
        }

二、事件流:事件冒泡和事件捕获

(一)事件流

事件流原理图.png

1、一个完整的JS事件流是从window开始,最后回到window的一个过程

2、事件流被分为三个阶段(1 ~ 5)捕获过程、(5 ~ 6)目标过程、(6 ~ 10)冒泡过程

(二)事件冒泡

1.先做练习:

做3个div嵌套,并都绑定一个事件,点击某个div时,弹出这个div的id

    <div id="div1">
        <div id="div2">
            <div id="div3"></div>
        </div>
    </div>
    <script type="text/javascript">
        var oDiv = document.getElementsByTagName("div");
        for(var i=0;i<oDiv.length;i++){
            oDiv[i].index = i;
            oDiv[i].onclick = function(){
                alert(this.id);
            }
        }
    </script>
2.问题:

点击div1时弹出div1;点击div2时弹出div2,div1;点击div3时,弹出div3,div2,div1。

3.原因:

当一个元素接收到事件时,他会把它接收到的信息向他的父级传递,父级继续传递给他的父级,直到顶层,这就是事件冒泡,事件冒泡是默认存在的。

4.事件绑定:

事件绑定实际上是给元素绑定事件所处理的函数;即使没有写事件函数,在你点击时onclick点击事件也会触发,就是没有函数执行,不会有所动作。

5.阻止冒泡:

如果不需要,阻止事件冒泡就可以了;在事件函数中调用
(1)event.cancleBubble = true;

    <div id="div1">
        <div id="div2">
            <div id="div3"></div>
        </div>
    </div>
    <script type="text/javascript">
        var oDiv = document.getElementsByTagName("div");
        for(var i=0;i<oDiv.length;i++){
            oDiv[i].index = i;
            oDiv[i].onclick = function(){
                alert(this.id);
                event.cancleBubble = true;    //阻止当前对象的当前事件的冒泡,而其他对象的事件冒泡不会被阻止
            }
        }
    </script>
        

(2)event.stopPropagation();将上述代码中的event.cancleBubble = true;替换即可。

(三)事件捕获

1.定义:

从外向内执行所有有事件的元素,因此会先执行最外面(父元素),然后依次向内执行直到执行的那个元素,这就是捕获过程;而冒泡机制刚好相反,捕获只监视进入的事件触发时执行,而冒泡只监视出去的事件触发时执行。

2.事件捕获:

只有标准浏览器下才有;
obj.addEventListener(事件名称,事件函数,是否捕获)
最后一个参数为true时会发现弹出顺序和之前相反了

三、事件处理程序

(一)定义:

事件就是用户或浏览器执行的某种动作。如:click,mouseover,load,都是事件名字。
而响应某个事件的函数就叫事件处理程序。事件处理程序名字以on开头。如:onclick,onmouseover,onload。

(二)形式:

1.DOM0级事件处理程序

每一个元素都有自己的事件处理程序属性,例如:onclick,将这种属性的值设置为一个函数,就可以指定事件处理程序。(其实就是一般的事件绑定)

        var oDiv = document.getElementsByTagName("div")[0];
        oDiv.onclick = function(){
            alert(123);
        }

注意:this指当前元素,即oDiv

2.DOM2级事件处理程序:

obj.addEventListener(事件名称,事件函数,是否捕获)

  • 三个参数:要处理的事件名、要处理的函数、布尔值
  • 特点:
    (1)冒泡阶段;
    (2)事件名称没有on;
    (3)时间执行顺序——顺序
    (4)this指向该事件的对象
    默认:是否捕获默认为false,false:冒泡;true:捕获
  • 添加多个事件处理程序
        var oDiv = document.getElementsByTagName("div")[0];
        oDiv.addEventListener("click",function(){
            alert(123);
        },false);
        oDiv.addEventListener("click",function(){
            alert(456);
        },false);

注意:按照添加的顺序触发,即先弹出123,在弹出456;

  • 删除事件处理程序obj.removeEventListener(事件名称,事件函数,是否捕获),与绑定参数完全相同,但是当第二个参数即函数为匿名函数时无法删除。
        var oDiv = document.getElementsByTagName("div")[0];
        oDiv.addEventListener("click",function(){
            alert(123);
        },false);
        oDiv.removeEventListener("click",function(){          //没有用
            alert(123);
        },false);
3.IE事件处理程序:obj.attachEvent(事件名称,事件函数)
  • 两个参数:事件处理程序名称、要处理的函数
  • 特点:
    (1)冒泡阶段;
    (2)事件处理程序名称有on;
    (3)时间执行顺序——倒序
    (4)this指向该事件的window
  • 添加多个事件处理程序
        var oDiv = document.getElementsByTagName("div")[0];
        oDiv.attachEvent("onclick",function(){
            alert(123);
        });
        oDiv.attachEvent("onclick",function(){
            alert(456);
        })

注意:按照添加的倒序触发,即先弹出456,在弹出123;

  • 删除事件处理程序obj.detachEvent(事件名称,事件函数),与绑定参数完全相同,但是当第二个参数即函数为匿名函数时无法删除。
        var oDiv = document.getElementsByTagName("div")[0];
        oDiv.attachEvent("onclick",function(){
            alert(123);
        });
        oDiv.detachEvent("onclick",function(){        //没有用
            alert(123);
        });

(三)兼容写法

1.函数的call()方法

当定义了函数时,函数会有个call()方法:fn1()=fn1.call(),区别是用call()方法的第一个参数可以改变内部this的指向(null时为原本该指向的),后面的参数是正常的参数

2.示例
        function bind(obj,evname,fn){
            if(obj.attachEvent){
                obj.attachEvent("on"+evname,function(){
                    fn.call(obj);
                });
            }
            else{
                obj.addEventListener(evname,fn,false);
            }
        }
        bind(document,'click',function(){alert(1)});
        bind(document,'click',function(){
            document.body.innerHTML = "我被点击了!!!!!!!!!!";
        });
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容