Javascript事件总结(一)

最近在项目中使用原生的javascript,不依赖任何类库开发通用组件,发现真的是“成也jQuery,败也jQuery”。离开jQuery都不会写js代码了,一个组件花费的大部分时间,在使用jQuery的情况下都可以分分钟搞定。这其中问题比较大的一块就是javascript事件,下面认真总结一下。


事件流

第一个要提的概念就是事件流。在很久很久以前,浏览器的开发团队遇到一个问题:当用户点击一个a 标签的时候,他是否也点击了p 标签?是否也点击了div 呢…

<body>
    <div>
    	<p><a href='http://keenwon.com/1095.html'>Javascript事件总结<a></p>
    </div>
</body>

IE和Netscape的团队在这个问题上的认识是一致的:用户的点击事件不止发生在a 标签上,也发生在p div …上。那么总要有个顺序吧?事件流就是描述这个顺序的。但是IE和Netscape提出了相反的事件流概念,IE的事件冒泡和Netscape的事件捕获

还拿上面的代码说,事件冒泡是由具体元素逐级传播到不具体的节点。就是a ->p ->div ->body ->html ->Document,所有现代浏览器都支持事件冒泡,IE9、chrome、firefox还会传播到window对象(点击在线测试)。而事件捕获刚好相反,不具体的节点先接受事件,具体的事件后接受事件,它的用意是在事件到达预定目标之前捕获它,同样的,IE9、chrome、firefox也是从window对象开始捕获的。

这两家浏览器厂商对着干,这时候我们的“规范”就要跳出来统一他们了,“DOM2级事件”规范规定的事件流包含3个阶段:事件捕获阶段,处于目标元素的阶段和事件冒泡阶段,他们依次发生。但是规范只是规范,实际情况是,IE8以及更早的版本不支持DOM2级事件,IE9、chrome、FireFox会在捕获和冒泡两个阶段涉及目标元素,所以目标元素的事件有两次被触发的机会。


事件处理程序

click,load之类的是事件,那么响应事件的函数就是事件处理程序。为事件指定处理程序的方式有:HTML事件处理程序,DOM0级事件处理程序,DOM2级事件处理程序,IE事件处理程序。

HTML事件处理程序

代码如下:

<input type="button" value="Click Me" onclick="alert('click')" />

onclick执行的函数封装了event 变量,可以直接访问事件对象。而this 就是事件的目标元素。例如:

<input type="button" value="Click Me" onclick="alert(event.type)" />
<input type="button" value="Click Me" onclick="alert(this.value)" />

onclick后面这个动态创建的函数,可以直接访问document以及该元素本身的成员,如果当前元素是表单的一部分,还可以直接访问表单元素,因为它使用with 扩展了作用域。

function (){
    with(document){
        with(this.form){
            with(this){
                //...
            }
        }
    }
}

使用示例:

<form>
    <input type="text" name="username" />
    <input type="button" value="click" onclick="alert(username.value)" />
</form>

直接使用username.value 就可以访问好name为username的文本框的值,在线测试

DOM0级事件处理程序

代码如下:

var btn = document.getELementById('myBtn');
btn.onclick = function(){
    alert('click');
}

DOM0级事件处理程序被当做是元素的方法,所以可以this 使用访问到元素的属性,例如用this.id 访问ID。DOM0级事件处理程序会在事件流的冒泡阶段被处理(第一个例子中就使用了DOM0级事件处理程序)。另外,也可以通过设置为null 来删除。

DOM2级事件处理程序

DOM2级事件定义了两个方法,用来添加和删除处理程序:addEventListener()removeEventListener() 。接受三个参数:要处理的事件名,作为事件处理程序的函数和一个表示事件阶段的布尔值(true-事件捕获阶段,false-事件冒泡阶段)。这个很经常用就不多说了,只要注意IE9+才支持就好了,有问题欢迎留言交流。

IE事件处理程序

IE实现了与DOM类似的两个方法,:attachEvent()detachEvent() ,因为IE8只支持事件冒泡,所以这两个方法只有两个参数。例如:

var btn = document.getElementById('btn');
btn.attachEvent('onclick',function(){
    alert(1);
});

注意它的第一个参数是“onclick”,不是“click”。还有一点就是 this 不是当前元素,而是window。

跨浏览器的事件处理程序

最后给出跨浏览器的解决方案:

function addHandler(element, type, handler){
    if(element.addEventListener){
        element.addEventListener(type, handler, false);
    } else if(element.attachEvent){
        element.attachEvent('on'+type, handler);
    } else {
        element['on'+type] = handler;
    }
}

移除事件的兼容方案同理,我比较懒就不写了。



标签:

无觅相关文章插件,快速提升流量