首頁 > web前端 > js教程 > 主體

談談我對JavaScript DOM事件的理解_javascript技巧

WBOY
發布: 2016-05-16 15:24:54
原創
1749 人瀏覽過

什麼是事件?

事件(Event)是JavaScript應用跳動的心 ,也是把所有東西黏在一起的膠水。當我們與瀏覽器中 Web 頁面進行某些類型的互動時,事件就發生了。事件可能是使用者在某些內容上的點擊、滑鼠經過某個特定元素或按下鍵盤上的某些按鍵。事件也可能是 Web 瀏覽器中發生的事情,比如說某個 Web 頁面載入完成,或是使用者捲動視窗或改變視窗大小。

透過使用 JavaScript ,你可以監聽特定事件的發生,並規定讓某些事件發生以對這些事件做出回應。

DOM與事件是JavaScript最核心的組成部分之一,他們賦予了頁面無限的想像空間,你根本無法離開他們,否則js將寸步難行。在我們平時的開發過程中,jQuery的出現使得我們得心應手,然而你必須知道,jQuery之所以把事情簡單化,是得益於JavaScript本身提供的強大的API,你應​​該去熟悉它們。

首先,此文不討論繁瑣細節,但是考慮到讀者的心靈感受,本著以積極向上的心態,在此還是會列舉示例說明。

標題為理解DOM事件,那麼在此拿一個簡單的點擊事件為例,希望大家看到這個例子後能觸類旁通。
 最初我們給頁面實作點擊,就像下面這樣的簡單操作。

先定義一個區塊如

微宇宙
,之後在內部實作id為weiyuzhou的點擊事件,如下程式碼所示:
var wyz = document.getElementById('weiyuzhou');
wyz.onclick = function () {
  confirm(arguments.length)
} 
登入後複製

确保上面这些步骤都没问题的话,我们才可以继续的往下走,然后我们在IE浏览器(低版本)看到弹出0,确切的说,IE8以下(包含IE8)的弹出0,反之弹出1。接着我在firefox浏览器看到弹出1。也就是说在IE8以下版本事件的触发不存在于函数的作用域内部,是不是说IE8以下的事件触发发生在全局作用域中,此处留个悬念,但是,可以肯定的是IE8以下事件的方法并没有这个Event参数,也就是说arguments的长度为0,如下视图5-02所示:

5-02

于是,我们看firefox浏览器窗口弹出1,说明事件存在于函数内部,再次证明方法的内部数组arguments长度为1,并且是可枚举的变量,也可以说可写,如下视图5-03所示。

5-03

如果,你还是不明白其中的原理,你不防去看一下《web前端开发修炼之道》书上第169页,然后再回过头来看此处文章摘要,可能会让你更加深层次的了解书中的内容。

接下来,我们该怎么办呢,我们肯定不能让IE和firefox返回的事件输出不相同,那么如何让IE和firefox下弹出的内容都一样。

衔接上一段内容,下面给点击函数的内部设置一个参数,参数名为e,然后在IE和firefox浏览器下面同时触发点击事件,我们看到firefox下面显示e为鼠标事件[object MouseEvent],IE8下报错,弹出错误信息未定义undefined。此时你要问我错在哪里,咱们回到刚刚的那句话‘此处留个悬念'进行分析,IE8以下的浏览器的事件是不是发生在全局作用域中,从视图5-02所示看到有一个global全局对象,我们可以对global展开搜索,global的继承的方法有一个event事件,找到了IE8的专有事件方法window继承event,于是我们对这个参数e设置为window.event进行一个调试,目前我们在IE8下面看到返回了一个事件[object event],如图5-04所示。

5-04

 

想必你一定发现了IE8和firefox浏览器下对话框的事件返回值各不不同,IE8的对话框[object MouseEvent],firefox的对话框[object event],那我们怎么让IE8和firefox下的返回值都相同呢?

看到这里,你的心里是不是有点小沮丧,挖坑挖了这么久了,怎么还没有看到水流出来,别急,正题才刚刚开始,咱们不闲聊,继续围绕正题展开分析,通过刚刚的返回值,我们继续使用断点的方法寻找能够实现IE和firefox的返回值的共同点。

经由以上分析,我们查找发现firefox下的event有我们需要的方法名可以被调用,当然,我们查找发现IE8下面的srcElement也有我们所需的方法名可以被调用,于是乎,呵呵!看到这里你的内心是不是有点小激动,一步步排除,最后发现也没有什么难的。回到正题,现在我们声明一个变量var e_child = e.srcElement || e.target; 然后我们在IE8和firefox浏览器上看到对话框信息都为[object HTMLDivElement],如图5-05所示。

5-05

 

现在我们解决了不同浏览器的返回值不同的问题,也就是说解决了兼容的问题,这只是冰上一角。

下面我们要解决实现窗口的容器触发事件,主要是基于上面的结构进行的一次分析。

当你有了上面基础的话,下面的内容相对于上面而言比较简单一点。

还是以上一个页面的块为例,现在我继续往块

微宇宙
增加一個子容器,這個子容器為行內元素koringz,取id名為coz,然後給這個元素也加一個點擊事件代碼同上函數,為了能區分開文本內容之間的差異。

當我分別在IE8和firefox下點擊容器的內容,出現了怪異的情況,在firefox瀏覽器的窗口上點擊時,點擊中文文本內容彈出來對話框'微宇宙',我再點擊koringz時,發現彈出了二次對話框,彈出內容都為'koringz',那是因為我點擊子容器的時候觸發了上一層的點擊行為,如何解決點擊koringz彈出二次對話框的問題,了解一點js的程式設計師都知道這是冒泡事件。

那麼在firefox能夠清除冒泡事件的是event下的stopPropagation,於是我們給第二次點擊事件函數代碼塊之後面加一行代碼e.stopPropagation();之後再點擊koringz發現彈出一次'koringz' 。如圖5-06所示

 5-06

 

接下來在IE8下面測試一下,發現在IE8瀏覽器點擊也彈出二次,解決IE8的停止冒泡事件為cacelBubble,且我們只需要給cacelBubble設定為true即可。

因為IE8下global包含的event屬性cacelBubble不是方法,而是輸出布林值的對象,所以這個和firefox有所不同,只是firefox把此事件封裝成方法而已。好了,現在我們給第二次點擊的事件程式碼區塊之後再加一行程式碼e.cancelBubble = true;然後在IE8瀏覽器下測試,之後再點擊koringz發現也彈出一次。如圖5-07所示

5-07

 

注意上面的停止冒泡的事件的程式碼可以根據瀏覽器的不同分開來寫,如何分開寫,我們查看IE8瀏覽器下面的document發現存在對象all,而在firefox卻沒有沒有這個all屬性,這也就是說document.all是IE8版本下面獨有的屬性。透過它我們可以區分瀏覽器的冒泡事件。

到目前為止,我們解決了視窗的冒泡事件,接下來,我們要解決一個事件因被多人定義而覆蓋原函數的問題。也可能是說某公司之前的工作人員添加了此事件,後來新員工接手專案後添加修改此事件而覆蓋了原事件的執行所產生的問題。也就是說給當前id多次新增此類事件都不會覆寫此事件的原函數執行。

在firefox下的window包含有addEventListener(type, listener, useCapture)的方法,隨後我們在內部定義此監聽事件domElement.addEventListener('click' ,function(e){confirm(e+'e')},false);,接著在firefox瀏覽器點擊內容彈出二次,最後一次彈出為[object MouseEvent]e,後面多了一個e,這是我有意加上用以區別的。如圖5-08所示。

5-08

 

接下來在IE8下測試發現addEventListener錯誤,但看到window下有此類方法(試了一下,原來此類方法在IE9以上版本是可以被支援),IE8同時還有一個attachEvent(event, pdisp),那麼我們設定監聽事件wyz.attachEvent('onclick',function(e){confirm(e + 'e')}),註:event為'onclick',緊接著在IE8下點擊發現可彈出二次,最後一次eIE。此時on('click',pdisp)和attachEvent(event,pdisp)可以共同使用。

綜上所述,我們解決了DOM事件的兼容性,DOM事件的冒泡,以及DOM事件的重用。

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板