更多相关内容见博客 github.com/zhuanyongxi…javascript
html标签中的写法html
<image id="element" src="hello.png" onclick="alert('Hi')"/>
复制代码
在JS中的绑定方法:vue
var element = document.getElementById("element");
element.onclick = function(e) {}
复制代码
dom0是节点元素的私有属性。同一个事件只能绑定一个,绑定多个,只有最后一个有效。直接写在html节点上的也会被覆盖。以下面的代码,最后点击触发的时候只会打印3。java
var element = document.getElementById("element");
element.onclick = function(e) {console.log(1)};
element.onclick = function(e) {console.log(2)};
element.onclick = function(e) {console.log(3)};
复制代码
因此,在使用如window.onload
之类的事件的时候就须要注意了。git
有标准,不涉及实践。github
addEventListener
方法在节点对象的原型链上。绑定实名函数更好,由于能够移除。第三个参数用于选择在什么阶段触发,默认false表示在冒泡阶段触发。编程
element.addEventListener('change',function(){},false)
复制代码
与DOM0的相比,DOM2事件能够绑定多个,以下,1和2都会被打印:设计模式
element.addEventListener('change', function() {console.log(1)}, false);
element.addEventListener('change', function() {console.log(2)}, false);
复制代码
但是,在绑定实名函数的时候,若是事件、函数名和触发阶段彻底相同的话,最终也是只有最后一个有效,以下,最终事件触发的时候只会打印出一个1:api
function fn() {console.log(1)};
element.addEventListener('change', fn, false);
element.addEventListener('change', fn, false);
复制代码
此外,addEventListener
还能够绑定DOM0中没有的事件,如DOMContentLoaded。浏览器
与DOM2的区别在于事件的种类,其余的同样。如keyup
、keydown
、keypress
都是DOM3的事件,click
也是DOM3级事件,具体到MDN中搜索DOM L3
。
简要的说就是事件的三个阶段:捕获阶段--目标阶段--冒泡阶段。详细说就是以下图。
当用户点击浏览器窗口,事件发生,捕获阶段开始:window--document--html--body--父节点--目标节点(目标阶段),而后开始冒泡阶段:目标节点--父节点--body--html--document--window。
几个须要注意的api:
preventDefault的做用是阻止浏览器默认行为,什么是默认行为?除了你本身绑定的操做以外的行为都是浏览器的默认行为,如a标签的跳转,表单的提交,鼠标右键呼出菜单等等。
此外event.returnValue = false;
、return false;
也能够达到跟proventDefault
一样的效果。若是是a标签,阻止跳转,能够href="javascript:;"
或href=javascript:void 0;
stopPropagation的做用是阻止事件的传播。阻止的是其余节点上的事件。
stopImmediatePropagation的做用也是阻止事件的传播。它不但能阻止其余节点上的事件,当前节点上的其余未触发的事件也会一并阻止。以下代码,只打印1:
element.addEventListener('click', function(event) {
event.stopImmdiatePropagation();
console.log(1);
}, false);
element.addEventListener('click', function() {console.log(2)}, false);
复制代码
currentTarget,当前会执行的回调函数绑定的那个节点。
elementFirst.addEventListener('click', function(event) {
console.log(event.currentTarget); // elementFirst
}, false);
elementSecond.addEventListener('click', function(event) {
console.log(event.currentTarget); // elementSecond
}, false);
复制代码
target,就是事件流中的目标阶段的那个节点,也就是目标节点。须要注意的是,事件是否发生与是否绑定的操做没有关系,即使没有在一个节点上绑定事件的操做,事件依然会发生。target
能够在事件委托中使用。
var myEvent = new Event('theEvent');
theTarget.addEventlistener('theEvent', function() {doSomething()})
theTarget.dispatchEvent(myEvent); // theTarget是一个节点,或者说是一个能够调用addEventListener方法的对象。
复制代码
此外customEvent
作到跟Event
一样的效果,他们的区别在于,customEvent
能够加一些本身须要的数据进去,不过兼容性没有Event
好。
用Event
建立了实例以后,也能够用myEvent.data = {}
的方式给数据,效果是同样的。
这有什么用?能够用来作全局范围内的广播,使模块间解耦。在vue中有一个用于组件间通信的EventBus,自定义事件就能够用来实现这一功能。
事件委托就是把原本应该由你来作的事情,让别人帮忙作一下。
在实际编程中,可能会出现这样的场景,一个节点下有多个子节点,每一个子节点都要有相应的事件绑定,这个时候咱们就能够利用事件的冒泡,把事件绑定在父节点上,而后用event.target
来区分究竟是哪一个子节点触发的事件。当这些子节点须要动态增减的时候,使用事件委托就显得尤其方便了,不管是写代码的效率仍是程序运行的效率都会更高。
局限性:focus、blur这样的事件没有在冒泡机制,没法委托。另一些消耗较高的事件如mousemove和mouseout也不适合委托。以下图
若是咱们把B区域的mousemove事件委托到A区域,当事件在A区域发生的时候,对应的操做也会执行,若是是消耗较低的事件,就不会有太大的影响,可若是是消耗较高的事件,就会显得有点浪费了。
这两种设计模式与事件很是的相似。与事件的区别在于,事件是异步的,而咱们本身实现的这两种模式,虽然使用了回调函数,但大都是同步的。而这两种设计模式之间的区别在于,发布订阅模式的事件池是统一的,观察者模式的事件池分散在各个发布者上面。
参考文章