第十三章:事件(事件对象)

事件

事件对象

  • 触发DOM上的某个事件后,会产生一个事件对象event,这个对象包含着所有与事件有关的信息。所有浏览器都支持event对象,但方式有所不同。

DOM中的事件对象

  • 兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论指定事件处理程序使用什么方法(DOM0级或DOM2级),都会传入event对象。
    var btn = document.getElementById("btn");
    //DOM0级
    btn.onclick = function(e) {
        alert(e.type);//"click"
    }
    //这里即使不给第一个参数取别名,直接调用event.type也是可以的,如下
    btn.onclick = function(e) {
        alert(event.type);//"click"

        alert(event == e);//true 这里的event是请求到了window下的event
        alert(event == window.event);//true
        //window.event = null; 加上这段 下面为false
        //alert(event == e);//false
    }
    //DOM2级
    btn.addEventListener("click", function(e) {
        alert(e.type);//"click"
    });
  • 而通过HTML直接指定事件处理程序,变量event中会保存event对象。
<button id="btn" onclick="alert(event.type)">click</button>
//我觉得可以把这块代码想成是
function(event) {
    with(document) {
        with(this) {
            alert(event.type);
        }
    }
}
//不过这种想象是错的,其实是访问了window.event。
  • 下面是event对象的属性和方法:
属性/方法类型读/写说明
bubblesBoolean只读表明事件是否冒泡
cancelableBoolean只读表明是否可以取消事件的默认行为
currentTargetElement只读其事件处理程序当前正在处理事件的那个元素
defaultPreventedBoolean只读为true表示已经调用了preventDefault(DOM3级事件新增)
detailInteger只读与事件相关的细节信息
eventPhaseInteger只读调用事件处理程序的阶段:1.捕获阶段;2.“处于目标”;3.冒泡阶段
preventDefault()Function只读取消事件的默认行为。如果cancelable为true则可以使用这个方法。
stopImmediatePropagationFunction只读取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级事件新增)
stopPropagationFunction只读取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法。
targetElement只读事件的目标
trustedBoolean只读为true表示是浏览器产生的。为false表示是由开发人员通过JS创建的(DOM3级事件新增)
typeString只读触发事件的类型
viewAbstractView只读与事件关联的抽象视图。等同于发生事件的window对象
  • 这里说一下this、currentTarget、target的异同点。在事件处理程序内部,对象this始终等于currentTarget的值。而target则是指向触发事件的实际目标。举个例子,当你点击了页面中的一个按钮,在body的事件处理程序中,this和currentTarget都会指向body。但target则指向了按钮。但是在按钮的事件处理程序中,这三个值相等
<input type="button" id="myBtn" value="Click Me" />

    var btn = document.getElementById("myBtn");
    btn.onclick = function(event){
        alert(event.currentTarget === this);//true
        alert(event.target === this);//true
    };

    document.body.onclick = function(event){
        alert(event.currentTarget === document.body);   //true
        alert(this === document.body);                  //true
        alert(event.target === document.getElementById("myBtn")); //true
    };
    /*btn.addEventListener("click", function (event) {
        alert(event.currentTarget === this);//true
        alert(this);//按钮。我觉得这个比较神奇,因为按照我的理解这个应该是window
        alert(event.target === this);//true
    })*/
  • type的用处是可以知道该事件属于哪种事件。所以当我们要用同一个方法去处理多种事件类型时,可以判断type的值来执行不一样的代码块。例子省略。
  • 要阻止特定事件的默认行为,可以使用preventDefault()方法。例如,链接的默认行为就是在单击时会导航到其href特性指定的URL。我们通过下面的代码可以阻止这种行为。
    <a href="http://write.blog.csdn.net/" id="myLink">Click Me</a>
    <script type="text/javascript">
        var link = document.getElementById("myLink");
        link.onclick = function(event){
            alert(event.cancelable);//true代表能够阻止默认行为
            event.preventDefault();
        };    
    </script>
  • stopPropagation()方法用于停止事件在DOM层次中的传播,即取消进一步的事件捕获或冒泡。例如,在按钮上调用该方法,则可以避免body的事件处理程序的执行(因为这个事件不再冒泡了)。
    <input type="button" value="Click Me" id="myBtn" />
    <script type="text/javascript">
        var btn = document.getElementById("myBtn");
        btn.onclick = function(event){
            alert("Clicked");
            alert(event.bubbles);//true 表明事件会冒泡
            event.stopPropagation();
        };

        document.body.onclick = function(event){
            alert("Body clicked");
        };
    </script>
  • 书上没有说明event.bubbles(是否冒泡)这个属性对event.stopPropagation()的具体影响。我觉得如果一个事件不会冒泡的话,是不是就意味着该浏览器只会捕获?貌似现代浏览器都支持冒泡,只有一些古代浏览器不支持冒泡。如果抛开这些古代浏览器不讲,只会捕获的浏览器也就意味着默认设置的事件处理程序并不会执行(默认都是在冒泡阶段执行),既然事件本身都不会执行,那停止事件在DOM层次中的传播也就没有意义了。
  • 事件对象的eventPhase属性,可以用来确定事件当前处于事件流的哪个阶段。值得一提的是,即使处于目标阶段发生在冒泡阶段,但仍然将其与其他冒泡阶段区别开了。
    <input type="button" value="Click Me" id="myBtn" />

    <script type="text/javascript">
        var btn = document.getElementById("myBtn");
        btn.onclick = function(event){
            alert(event.eventPhase);   //2 处于目标阶段 
            //这个阶段的target和currentTarget相等。
        };

        document.body.addEventListener("click", function(event){
            alert(event.eventPhase);   //1 捕获阶段
        }, true);//fasle = 不传 = 默认 = 冒泡

        document.body.onclick = function(event){
            alert(event.eventPhase);   //3 冒泡阶段
        };//DOM0级 = 默认 = 冒泡

    </script>
  • 在事件处理程序执行期间,event对象才会存在。一旦事件处理程序执行完毕,event对象就会销毁。且window.event会根据当前事件流的阶段不断更新。

IE中的事件对象

  • 这一部分的主体是IE8-浏览器,IE9+虽然也可以这么用,但是还是推荐用前面说的方法。
  • 在IE中访问event对象有几种不同的方式,取决于指定事件处理程序的方法。在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在。
    var btn = document.getElementById("myBtn");
    btn.onclick = function(event){
        alert(event);//IE8- undefined IE9+或者其他浏览器[Object MouseEvent]
        event = window.event;
        alert(event.type);   //2
    };
  • 当事件是attachEvent()添加的,可以用下面的方法:
    var btn = document.getElementById("myBtn");
    btn.attachEvent("onclick", function (e) {
        //默认也会有event这个局部变量
        // 但是神奇的是在IE中event居然不等于window.event
        alert(event == window.event);//false
        alert(event.type == window.event.type);//true
        //且这两个也不相等
        alert(event == e);//false
        alert(event.type == e.type);//true
        // 且这两个也不相等...厉害了我的哥
        alert(window.event == e);//false
    })
  • 那么问题来了,window.event != e ,我们可以强行认为这种方式在调用事件处理程序时不会动态的改变window.event。那为什么event != window.event,如果这两个不是一个东西,那这个event到底是在哪?按照作用域链的知识,这里event没有报错,那他就只能存在于匿名函数内部或者全局作用域,可是它又和全局作用域下的不同。匿名作用域中又没有指定,这是怎么回事???
  • 先放放,我也不知道原因是什么。。。

  • 如果是HTML特性指定的事件处理程序,这种情况和之前一样,可以直接通过event变量来访问event对象。

<input type="button" value="Click Me" id="myBtn" onclick="alert(event.type);alert(event == window.event)"/>
//弹出是click和false。依旧是false,还是无法解释。
  • IE中的event事件对象也包含与创建它的事件相关的属性和方法,不同事件类型属性和方法也有差异,以下是所有事件都包含的一些属性和方法。
属性/方法类型读/写说明
cancelBubbleBoolean读/写默认值为false,设置为true可以取消事件冒泡(IE8-中事件处理程序只在冒泡阶段执行,与DOM中的stopPropagation()作用相同)
returnValueBoolean读/写默认值为true,设置为false可以取消事件的默认行为(preventDefault()
srcElementElement只读事件的目标(target
typeString只读被触发的事件的类型
  • 因为事件处理程序的作用域是根据指定它的方式来确定的,所以不能认为this会始终等于事件目标。故而,最好还是使用event.srcElement比较保险,来看下面的例子:
    var btn = document.getElementById("myBtn");
    //下面两种方式顺序无关,不会互相覆盖
    btn.onclick = function(){
        alert(window.event.srcElement === this);      //true
        alert(this)//这个this指向btn,因为这个函数是btn的一个属性
    };
    btn.attachEvent("onclick", function(event){
        alert(event.srcElement === this);             //false
        alert(this)//这个this指向window,因为这是一个匿名函数
    });
    document.onclick = function(){
        alert(window.event.srcElement === this);      //false 点击的是input
    };
  • 另外两个属性大同小异。下面是书中的例子,就不解释了。
<a href="http://write.blog.csdn.net/" id="myLink">Click Me</a>
<script type="text/javascript">
    var link = document.getElementById("myLink");
    link.onclick = function(){
        window.event.returnValue = false;
    };    
</script>

<input type="button" value="Click Me" id="myBtn" />
<script type="text/javascript">
    var btn = document.getElementById("myBtn");
    btn.onclick = function(){
        alert("Clicked");
        window.event.cancelBubble = true;
    };
    document.body.onclick = function(event){
        alert("Body clicked");
    };
</script>

跨浏览器的事件对象

  • 和前一篇文章末尾说的addHandle()方法类似,我们可以将上面的方法通过能力检测编写出一套跨浏览器的代码。这里不再详解。
var EventUtil = {
    getEvent: function(event){
        return event ? event : window.event;
    },

    getTarget: function(event){
        return event.target || event.srcElement;
    },

    preventDefault: function(event){
        if (event.preventDefault){
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },

    stopPropagation: function(event){
        if (event.stopPropagation){
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值