事件
内联HTML属性法
最简便的方式就是通过标签的特定属性来添加事件,例如:
<div onclick="alert('Ouch!');">click</div>
这种情况下,只要该div所在的区域被用户单击了,就会触发该标签的单击事件。与此同时,其onclick属性中的字符串就会被当做JavaScript代码来执行。尽管,这里没有显式指定监听单击事件的函数,但相关环节在幕后已经为此创建了一个函数,函数的代码就等于我们为onclick属性设定的值。
元素属性法
关于单击事件函数,我们还有另一种编写方式,那就是将其设置为DOM元素节点的属性。
<div id="my-div">click</div> <script type="text/javascript"> var myelement=document.getElementById('my-div'); myelement.onclick=function(){ alert('Ouch!'); alert('And double ouch!'); } </script>
DOM事件监听器
对于浏览器来说,最佳的事件处理方式当然某过于事件监听器了。通过这种方式,我们可以为一个事件指定多个监听函数。当事件被触发时,所有的监听器函数都会被执行。而且,这些监听器之间不需要知道彼此的存在,它们的工作是彼此独立的。任何一个函数的加入或退出都不会影响其他监听器的工作。
下面我们通过addEventListener()方法给单击事件赋予相关的监听器:
addEventListener()方法是基于某一节点对象来调用的。它的首参数是一个事件类型的参数,第二个参数是一个函数指针,它可以是function(){}这样的匿名函数,也可以说console.log()这样的现存函数。该监听器函数会在相关事件发生时被调用,调用时会接收到一个事件对象参数。
捕捉法与冒泡法
在之前调用addEventListener()方法的过程中,还处在一个第三参数false。假设我们有一个无序的链接列表,例如:
<body> <ul> <li><a href="http://phpied.com">my blog</a></li> </ul> </body>
当我们单击该链接时,实际上我们也单击了列表项<li>、列表<ul>、<body>乃至于整个document对象。总而言之,对该链接的单击也可以看做对document对象的单击,这就形成了一个事件传播链。这种事件传播过程的实现通常有两种方式:
- 捕捉法:单击首先发生在document上,然后依次传递给body、列表、列表项,并最终到达该链接
- 冒泡法:单击首先发生在该链接上,然后逐层向上冒泡,直至document对象。
按照DOM Leve2的建议,事件传播应该分成三个阶段:先在标签上使用捕捉法,而后使用冒泡法。也就是说,事件传播的路径应该是先从document到相关链接然后回到document。
从历史上来说,IE和Netscape的相关实现是高度不统一的。IE使用冒泡法,而Netscape则只使用捕捉法。而在DOM标准建立后,Firefox、opera以及Safari基本上完整的实现了上述的三个阶段,只有IE依然坚持只使用冒泡法。
addEventListener的第三个参数,决定代码是否采用捕捉法来处理事件。为了让我们的代码适用于更多的浏览器,最好还是始终将其设置为false,即只使用冒泡法来处理事件。
我们也可以在监听函数中阻断事件的传播,令其停止向上冒泡,这样一来,事件就不会再到达document对象那里了。为了做到这一点,我们就必须去调用相关事件对象的stopPropagation方法。
阻断传播
下面,我们来演示一下如何让事件停止它的冒泡式传播。我们来定义一个用于处理段落单击事件的函数:
function paraHandler(){alert('clicked paragraph');}
我们将该单击监听器设置给paragraph、body、document乃至整个浏览器的window对象。
现在,如果我们单击一下该段落,就会看到四个警告窗,它们分别是:
- clicked paragraph
- click body
- click document
- click window
这诠释了同一单击事件从具体标签向整个窗口传播的全过程,也就是向上冒泡的全过程。addEventListener()方法的对立面就是removeEventListener(),该方法参数与前者相同。下面,我们移除该段落上的监听器。
para.removeEventListener('click',paraHandler,false);
如果再次单击段落,就只会弹出body、document对象以及window对象的单击事件窗,不再有针对该段落的弹出窗了。要提醒的是,由匿名函数所定义的监听器是不能被移除的。因为如果我们要移除某个监听器,就必须获得之前那一个指定为监听器函数的指针。
下面,我们来阻断事件的传播,首先定义一个函数:
function paraHandler(e){ alert('clicked paragraph'); e.stopPropagation(); }
然后我们添加修改后的监听器:
para.addEventListener('click',paraHandler,false);
现在如果我们再单击段落,就会看到弹出窗只有一个了,因此该事件不会再被上传给body、document和window了。
防止默认行为
在浏览器模型中,有些事件自身就存在一些预定义行为。例如,单击链接会载入另一个页面。对此,我们可以为该链接设置监听器,并禁用器默认行为。要做到这一点,我们只需要在相关事件对象上调用preventDefault()方法。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步