javascript----事件


事件處理程序在應(yīng)用中是必不可少的,雖然現(xiàn)在很多框架都有自己實現(xiàn)事件處理方法,但是熟知原生才能讓我們應(yīng)對各種各樣的需求并且實現(xiàn)自己的想法


事件流

這個是很基本很基本的概念了
DOM2級事件規(guī)定的事件流包括三個階段:
①事件捕獲階段
②處于目標階段
③冒泡階段
并且明確要求捕獲階段不會涉及事件目標


事件處理程序

這里主要講DOM2級事件處理程序,HTML事件處理程序和DOM0級事件處理程序現(xiàn)在幾乎很少接觸,故跳過

DOM2級事件處理程序

addEventListener()
接收三個參數(shù):①要處理的事件名②事件處理程序③布爾值(true表示捕獲階段調(diào)用時間處理程序(建議),false表示冒泡階段)
removeEventListenser()
接收的參數(shù)與addEventListener一樣,需要注意的是,通過addEventListener()添加的匿名函數(shù)將無法通過removeEventListener()移除

IE事件處理程序

addEventListener在IE8及更早版本都不給予支持,但有類似的兩個方法:attachEvent()detachEvent(),同樣接收事件處理程序名稱和事件處理程序函數(shù)作為參數(shù),默認在冒泡階段調(diào)用
注意:
①這里的時間處理程序名稱沒有on前綴
②這里的時間處理程序會在全局作用域中運行,故this等于window

跨瀏覽器的事件處理程序

var EventUtil = {
    addHandler:function(element,type,handler){
        if(element.addEventListener){
            element.addEventListener(type,handler,false);
        }else if(elment.attachEvent){
            element.attachEvent("on"+type,handler);
        }else{
            element["on"+type] = handler;
               }
    },
    removeHandler:function(element,type,handler){
        if(element,removeEventListener){
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent){
            element.detachEvent("on"+type,handler);
        }else{
            element["on"+type] = null;
        }
    }
}

事件對象

事件對象包含著所有與時間有關(guān)的信息,包括導(dǎo)致事件的元素耘成、事件的類型以及其他與特定時間相關(guān)的信息.事件對象又分為DOM事件對象和IE事件對象,下面將分開總結(jié)

DOM中的事件對象

兼容DOM的瀏覽器會將一個event對象傳入到事件處理程序中,event對象包含與創(chuàng)建它的特定事件有關(guān)的屬性和方法,不同事件類型不一樣,不過所有事件都有下列共同的屬性和方法

  • bubbles 布爾值 表明事件是否冒泡
  • cancelable 布爾值 表明是否可以取消事件的默認行為
  • currentTarget 節(jié)點 其事件處理程序當前正在處理事件的那個元素
  • defaultPrevented 布爾值 是否被阻止了默認操作
  • detail Integer 與事件相關(guān)的細節(jié)
  • eventPhase Integer 調(diào)用事件處理程序的階段:1->捕獲 2->處于目標 3->冒泡
  • preventDefault() 取消事件的默認行為
  • stopImmediatePropagation() 取消事件的進一步捕獲或冒泡同時阻止任何事件處理程序被調(diào)用(DOM3)
  • stopPropagation() 取消事件的進一步捕獲或冒泡
  • target 節(jié)點 事件的目標
  • trusted 布爾值 是否為瀏覽器生成的
  • type 被觸發(fā)的事件的類型
  • view 與事件關(guān)聯(lián)的抽象視圖

注意:在事件處理程序內(nèi)部,對象this始終等于currentTarget,即相應(yīng)事件的元素,而不一定是觸發(fā)事件的元素,而event.target則指向觸發(fā)事件的元素

IE中的事件對象

要訪問IE中的event對象的方式取決于指定事件處理程序的方法:
①使用DOM0級添加事件處理程序時,event對象作為window對象的一個屬性存在
②使用attachEvent()添加的事件處理程序,會有一次event傳入事件函數(shù)中
③通過HTML特性制定的事件處理程序,可以通過一個叫event的變量來訪問event對象

IE的event對象同樣包含與創(chuàng)建它的事件相關(guān)的屬性和方法,但所有事件對象都會包含下面所列的屬性和方法

  • cancelBubble 布爾值 默認false,設(shè)置為true可以取消事件冒泡
  • returnValue 布爾值 默認true,但將其設(shè)置為false可以取消事件的默認行為
  • srcElement 事件的目標,與DOM中的target屬性相同
  • type 被觸發(fā)的事件的類型

跨瀏覽器的事件對象

var EventUtil = {
    addHandler:function(element,type,handler){
        if(element.addEventListener){
            element.addEventListener(type,handler,false);
        }else if(elment.attachEvent){
            element.attachEvent("on"+type,handler);
        }else{
            element["on"+type] = handler;
               }
    },
    removeHandler:function(element,type,handler){
        if(element,removeEventListener){
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent){
            element.detachEvent("on"+type,handler);
        }else{
            element["on"+type] = null;
        }
    },
    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;
        }
    }
}

事件類型

UI事件

  • load

當頁面完全加載后在window上觸發(fā),當圖像加載完畢時在img元素上觸發(fā)等

注意:對于新圖像元素,只要設(shè)置了src屬性就會開始下載,但script和link只有在把相關(guān)元素添加到文檔后才會開始下載

  • unload

在文檔被完全卸載后觸發(fā),利用最多的情況是清除引用,以避免內(nèi)存泄漏

  • resize

當瀏覽器窗口被調(diào)整到一個新的高度或?qū)挾葧r,就會觸發(fā)resize事件,建議在該事件的事件處理程序中不要加入大計算量的代碼,因為會被頻繁執(zhí)行,從而導(dǎo)致瀏覽器反應(yīng)變慢

  • scroll事件

發(fā)生滾動時觸發(fā),雖然在window對象上發(fā)生,但它實際表示的是頁面中相應(yīng)元素的變化,通常配合scrollLeft和scrollTop來使用

焦點事件

  • focus
  • blur

鼠標與滾輪事件

鼠標事件

  • click
  • dblclick
  • mousedown
  • mouseup
  • mouseenter 在鼠標從元素外部首次移動到元素范圍之內(nèi)觸發(fā)
  • mouseleave 在位于元素上方的鼠標光標移動到元素范圍之外時觸發(fā)
  • mousemove 當鼠標指針在元素內(nèi)部移動時重復(fù)地觸發(fā)
  • mouseout 當鼠標指針位于一個元素上方,然后用戶將其移入另一個元素時觸發(fā),又移入的另一個元素可能位于前一個元素的外部,也可能是這個元素的子元素
  • mouseover 在鼠標指針位于一個元素外部,然后用戶將其首次移入另一個元素邊界之內(nèi)觸發(fā)
  • mousewheel 當用戶通過鼠標滾輪與頁面交互薇溃、在垂直方向上滾動頁面都會觸發(fā)mousewheel事件

注意 除了mouseenter和mouseleave之外,所有鼠標事件都會冒泡

鼠標事件event特有屬性

  • 客戶區(qū)坐標位置:
    通過event.clientX和event.clientY來獲取鼠標光標距離視口的位置
  • 頁面坐標位置:
    通過event.pageX和event.pageY來獲取鼠標光標距離頁面的位置
  • 屏幕坐標位置
    通過event.screenX和event.screenY來獲取鼠標光標距離屏幕的位置
  • 修改鍵
    鼠標可能會配合修改鍵使用,可以通過event.shiftKey,event.ctrlKey,event.altKey,event.metaKey的布爾值來獲知對應(yīng)的修改鍵是否按下了,從而給予正確的反饋事件
  • 相關(guān)元素
    在發(fā)生mouseover和mouseout事件時,會涉及到更多的元素
    ①mouseover: 主目標是獲得光標的元素,相關(guān)元素是失去光標的元素
    ②mouseout: 主目標是失去光標的元素,相關(guān)元素是獲得光標的元素
    DOM中,event.relatedTarget表示相關(guān)元素
    IE8之前,前者用event.fromElement,后者用event.toElement來表示相關(guān)元素
  • 鼠標按鈕
    對于mousedown和mouseup事件,其event對象存在一個button屬性,表示按下或釋放的按鈕,在DOM中,button屬性有以下值
    0表示主鼠標按鈕
    1表示中間按鈕
    2表示次鼠標按鈕
    在IE8及之前版本中也提供button屬性,不過屬性值與DOM有很大差異
    這里有跨瀏覽器方案:
    var EventUtil = {
  //省略了其他代碼
   getButton:function(event){
    if(document.implementation.hasFeature("MouseEvents","2.0")){
        return event.button
    }else{
        switch(event.button){
            case 0:
            case 1:
            case 3:
            case 5:
            case 7:
                return 0;
            case 2:
            case 6:
                return 2;
            case 4:
                return 1;
        }
    }
    },
     //省略了其他代碼
    };

鼠標滾輪事件
mousewheel的event對象除包含鼠標事件的所有標準信息外,還包含一個特殊的wheelDelta屬性(IE,Opera,Chrome,Safari), detail屬性(Firefox)
在wheelDelta
向前滾動:wheelDelta是120的倍數(shù)
向后滾動:wheelDelta是-120的倍數(shù)
在detail
向前滾動:detail的值是3的倍數(shù)
前后滾動:detail的值是-3的倍數(shù)
此處有跨瀏覽器方案:
var EventUtil = { //省略了其他代碼 getWheelDelta:function(event){ if(event.wheelDelta){ return(client.engine.opera&&client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta); }else{ return -event.detail * 40; } } }

鍵盤與文本事件

有三個鍵盤事件和一個文本事件

  • keydown: 當用戶按下鍵盤上任意鍵時觸發(fā),按住不放則連續(xù)觸發(fā)
  • keypress: 當用戶按下鍵盤上字符鍵時觸發(fā),按住不放則連續(xù)觸發(fā)
    (Safari3.1之前的版本在按下非字符鍵時也會觸發(fā)
  • keyup: 當用戶釋放鍵盤上的鍵時觸發(fā)
  • textInput: 在文本插入文本框前會觸發(fā)textInput事件,用意是將文本顯示給用戶之前更容易攔截文本

鍵盤事件event特有屬性

  • 鍵碼
    在發(fā)生keydown和keyup事件時,event對象的keyCode屬性會包含一個代碼與對應(yīng)的按鍵對應(yīng)
  • 字符編碼
    發(fā)生keypress事件意味著按下的鍵會影響到屏幕中文本的顯示,因此在所有瀏覽器中,按下能夠插入或刪除字符的鍵都會觸發(fā)keypress事件

變動事件

  • DOMSubtreeModified:在DOM結(jié)構(gòu)中發(fā)生任何變化時觸發(fā)
  • DOMNodeInserted:在一個節(jié)點作為子節(jié)點被插入另一個節(jié)點時觸發(fā)
  • DOMNodeRemoved: 在節(jié)點從其父節(jié)點中被移除時觸發(fā)
  • DOMNodeInsertedIntoDocument:在一個節(jié)點被直接插入文檔或通過子樹間插入文檔之后觸發(fā)
  • DOMNodeRedmovedFromDocument:同理
  • DOMAttrModified:在特征被修改之后觸發(fā)
  • DOMCharacterDataModified:在文本節(jié)點的值發(fā)生變化時觸發(fā)

HTML5事件

  • contextmenu:單機鼠標右擊事件
  • beforeunload:在瀏覽器卸載頁面之前觸發(fā)
  • DOMContentLoaded:在頁面中的一切都加載完畢時觸發(fā),在形成完整的DOM樹之后就會觸發(fā)县钥,不理會圖像慷吊、js文件等資源是否下載完畢
  • readystatechange
    這個事件的目的時提供與文檔或元素的加載狀態(tài)有關(guān)的信息,支持此事件的每個對象都有一個readyState屬性
  • pageshow和pagehide事件(Firfox opera)
  • hashchange:在URL的參數(shù)列表發(fā)生改變時觸發(fā)

設(shè)備事件(略)

觸摸與手勢事件

觸摸事件
  • touchstart:當手指觸摸屏幕時觸發(fā)
  • touchumove:當手指在屏幕上滑動時連續(xù)地觸發(fā)
  • touchend:當手指從屏幕上移開時觸發(fā)
  • touchcancel:當系統(tǒng)停止跟蹤觸摸時觸發(fā)
    除了常見的DOM屬性外描焰,觸摸事件還包含下列三個用于跟蹤觸摸的屬性:
    (1)touches:表示當前跟蹤的觸摸操作的Touch對象的數(shù)組
    (2)targetTouchs:特定與事件目標的Touch對象的數(shù)組
    (3)changeTouched:表示自上次觸摸以來發(fā)生了什么變化的Touch對象的數(shù)組
手勢事件
  • gesturestart:當一個手指已經(jīng)按在屏幕上而另一個手指又觸摸屏幕時觸發(fā)
  • gesturechange:當觸摸屏幕的任何一個手指的位置發(fā)生變化時觸發(fā)
  • gestureend:但任何一個手指從屏幕上面移開時觸發(fā)咐容。
    注意:在一個元素上設(shè)置事件處理程序,意味著兩個手指必須同時位于該元素的范圍之內(nèi)滋捶,才能觸發(fā)手勢事件(這個元素就是目標)痛悯,由于這些事件冒泡,所以將事件處理程序放在文檔上也可以處理所有手勢事件重窟,此時事件的目標就是兩個手指都位于其范圍 內(nèi)的那個元素载萌。
    特殊屬性:
  • rotation:表示手指變化引起的旋轉(zhuǎn)角度,負值表示逆時針旋轉(zhuǎn)
  • scale:表示兩個手指尖距離的變化情況巡扇,這個值從1開始扭仁,并隨距離拉大而增長,隨距離縮小而減小

內(nèi)存和性能

事件委托

事件委托利用了事件冒泡厅翔,只指定一個事件處理程序乖坠,就可以管理某一類型的所有事件

EventUtil.addHandler(document,'click',function(event){
    event = EventUtil.getTarget(event);
    switch(target.id){
     case "dosomething":
             handleDosomething()
             break;
     case "goSomewhere":
            handleGosomgwhere()
            break;
  }
});

事件委托的優(yōu)點:

  • document對象很快就可以訪問,而且在頁面生命周期的任何時點上為它添加事件處理程序刀闷。換句話說熊泵,只要可點擊的元素呈現(xiàn)在頁面上,就可以立刻具備適當?shù)墓δ堋?/li>
  • 在頁面中設(shè)置事件處理程序所需的時間更少甸昏,只添加一個事件處理程序所需的DOM引用更少顽分,所花的時間也更少。
  • 整個頁面占用的內(nèi)存空間更少施蜜,能夠提升整體性能

模擬事件

DOM中的事件模擬
  • ①document.createEvent()創(chuàng)建一個event對象卒蘸,可接受一個參數(shù),表示要創(chuàng)建的事件類型的字符串(UIEvetnts,MouseEvents,MutationEvents,HTMLEvents)
  • ②創(chuàng)建的event對象都對應(yīng)有一個特殊的初始化方法翻默,傳入適當?shù)臄?shù)據(jù)可以初始化該evnet對象
  • ③在DOM節(jié)點上使用dispatchEvent()方法觸發(fā)這個事件
自定義事件

自定義事件不是由DOM原生觸發(fā)的額缸沃,它的目的是讓開發(fā)人員創(chuàng)建自己的事件。

  • ①調(diào)用document.createEvent('CustomEvent')創(chuàng)建一個自定義事件對象修械,有一個名為initCustomEvent()的方法接收以下4個參數(shù):
    • type(字符串):觸發(fā)的事件類型
    • bubbles(布爾值):表示時間是否應(yīng)該冒泡
    • cancelable(布爾值):表示事件是否可以取消
    • detaitl(對象):任意值趾牧,保存在event對象的detail屬性中
  • ②在對應(yīng)節(jié)點上綁定該事件
  • ③使用dispatchEvent(event)事件觸發(fā)。

此處跳過對IE的事件模擬肯污。

以上參考紅寶書《高程三》
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翘单,一起剝皮案震驚了整個濱河市梯皿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌县恕,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剂桥,死亡現(xiàn)場離奇詭異忠烛,居然都是意外死亡,警方通過查閱死者的電腦和手機权逗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門美尸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斟薇,你說我怎么就攤上這事师坎。” “怎么了堪滨?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵胯陋,是天一觀的道長。 經(jīng)常有香客問我袱箱,道長遏乔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任发笔,我火速辦了婚禮盟萨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘了讨。我一直安慰自己捻激,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布前计。 她就那樣靜靜地躺著胞谭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪残炮。 梳的紋絲不亂的頭發(fā)上韭赘,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音势就,去河邊找鬼泉瞻。 笑死,一個胖子當著我的面吹牛苞冯,可吹牛的內(nèi)容都是我干的袖牙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼舅锄,長吁一口氣:“原來是場噩夢啊……” “哼鞭达!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤畴蹭,失蹤者是張志新(化名)和其女友劉穎坦仍,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叨襟,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡繁扎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了糊闽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梳玫。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖右犹,靈堂內(nèi)的尸體忽然破棺而出提澎,到底是詐尸還是另有隱情,我是刑警寧澤念链,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布盼忌,位于F島的核電站,受9級特大地震影響掂墓,放射性物質(zhì)發(fā)生泄漏碴犬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一梆暮、第九天 我趴在偏房一處隱蔽的房頂上張望服协。 院中可真熱鬧,春花似錦啦粹、人聲如沸偿荷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽跳纳。三九已至,卻和暖如春贪嫂,著一層夾襖步出監(jiān)牢的瞬間寺庄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工力崇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留斗塘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓亮靴,卻偏偏與公主長得像馍盟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子茧吊,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 事件流 事件流描述的是從頁面中接受事件的順序贞岭。但是IE和Netscape開發(fā)團隊提出了差不多相反的事件流的概念八毯。I...
    losspm閱讀 265評論 0 0
  • 一、事件流 1.1 事件流 事件流:從頁面中接受事件的順序 事件冒泡:即事件開始時由最具體的元素(文檔中嵌套層次最...
    范小飯_閱讀 1,070評論 1 9
  • JavaScript 程序采用了異步事件驅(qū)動編程模型瞄桨。在這種程序設(shè)計風格下话速,當文檔、瀏覽器芯侥、元素或與之相關(guān)的對象發(fā)...
    劼哥stone閱讀 1,256評論 3 11
  • 事件基本概念 事件類型:用來說明發(fā)生什么類型事件的字符串尿孔,即事件名。事件目標:發(fā)生事件的對象筹麸。當談?wù)撌录r,會同時...
    留七七閱讀 1,028評論 0 11
  • 人生如戲,戲如人生留晚。在各自前進的路上酵紫,你會遇見許多人深啤,許多故事施戴,許多風景。幸福的是法竞,奔跑從未停止赋焕。你就要相...
    未及風深閱讀 1,946評論 1 3