事件處理程序過多也會導致性能問題?

在JavaScript中,添加到頁面上的事件處理程序數量將會直接關系到頁面的整體運行性能,主要有一下幾方面的原因

  • 每個函數都是對象,都會占用內存,對象越多,性能越差
  • 必須實現指定所有事件處理程序而導致的DOM訪問次數,會延遲整個頁面的交互就緒時間

要如何提升性能呢

  • 方案一:事件委托

事件委托利用了事件冒泡,只為一個元素(DOM樹中盡量高層次的元素)指定一個事件處理程序,就可以管理某一類型的所有事件
舉個例子,對于click事件,加入有多個元素都有該事件,不用事件委托我們會這么做,為每個元素逐一添加事件處理程序,當元素過多而且又不是調用同一處理函數時是非常麻煩的

//html
<body>
<div id="eles">
    <button id="btn1">1</button>
    <button id="btn2">2</button>
    <button id="btn3">3</button>
    <button id="btn4">4</button>
</div>

//JavaScript
window.onload = function () {
    var btn1 = document.getElementById('btn1');
    var btn2 = document.getElementById('btn2');
    var btn3 = document.getElementById('btn3');
    var btn4 = document.getElementById('btn4');

    var EventUtil = {
        addHandler: function (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;
            }
        }
    };

    EventUtil.addHandler(btn1, 'click', handler);
    EventUtil.addHandler(btn2, 'click', handler);
    EventUtil.addHandler(btn3, 'click', handler);
    EventUtil.addHandler(btn4, 'click', handler);

};
function handler(event) {
    console.log(event.target);
}

那么,利用事件委托我們可以像下邊這樣做

//JavaScript
window.onload = function () {
    var eles = document.getElementById('eles');

    var EventUtil = {
        addHandler: function (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;
            }
        },
        getEvent: function (event) {
            return event ? event : window.event.srcElement
        },

        getTarget: function (event) {
            return event.target || event.srcElement
        }
    };

    EventUtil.addHandler(eles, 'click', handler);

    function handler(event) {
        var event = EventUtil.getEvent(event);
        var target = EventUtil.getTarget(event);
        var eleId = target.id;
        switch (eleId) {
            case 'btn1':
                console.log('1');
                break;
            case 'btn2':
                console.log('2');
                break;
            case 'btn3':
                console.log('3');
                break;
            case 'btn4':
                console.log('4');
                break;
            default:
                console.log('err');
        }
    }
};

在這個代碼中我們為四個按鈕的父級元素添加了點擊事件,然后在事件處理程序中再去區分是哪一個按鈕,這樣做的好處是我們只去了一次DOM節點,也只添加了一次處理程序,占用內存更少,速度更快

如果可行,我們也可以為document元素添加事件處理程序來處理某一類型的多個事件,在事件發生元素多次數多的情況下事件委托是非常好的選擇,適合用事件委托技術的事件有click,mousedown,mouseup,keydown,keyupkeypress

總結一下事件委托的優勢
  • document對象很快就可以訪問,而且可以再頁面生命周期的任何時間點上為它添加事件處理程序(只要可單擊的元素呈現在頁面上,就可以立即具備適當的功能)
  • 在頁面上設置事件處理程序所需的更時間少(所需DOM引用少)
  • 整個頁面占用的內存更少

方案二:移除事件處理程序

有時候我們會通過innerHtml來替換某個元素的子元素,但假如這個子元素此時綁定著一些事件處理程序呢,假如直接替換,會導致原來的子元素雖然被移走,但是事件處理程序任然與子元素保持著引用關系,這個時候我們就需要在用innerHTML移除元素之前先移除它的事件處理程序,具體方法可看移除事件處理程序

還有一種情況就是卸載頁面的時候,如果在頁面卸載之前沒有處理干凈事件處理程序,那么它們就會留在內存中,不斷地跳轉或者刷新頁面會導致內存中滯留的對象數目越來越多,最好的做法就是在頁面卸載之前通過unload事件處理程序來移除掉所有的事件處理程序,和上一個方法聯系一下,假如用了事件委托來添加事件處理程序,那么在這個時候去移除所有的事件處理程序就會簡單很多.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,698評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,202評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,742評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,580評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,297評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,688評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,693評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,875評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,438評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,183評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,384評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,931評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,612評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,022評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,297評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,093評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,330評論 2 377

推薦閱讀更多精彩內容

  • JavaScript 程序采用了異步事件驅動編程模型。在這種程序設計風格下,當文檔、瀏覽器、元素或與之相關的對象發...
    劼哥stone閱讀 1,273評論 3 11
  • JavaScript 與 HTML 間通過事件實現交互。事件——文檔或瀏覽器窗口中發生的一些特定的交互瞬間,即用戶...
    sylvia_yue閱讀 487評論 0 0
  • 本章內容 理解事件流 使用事件處理程序 不同的事件類型 JavaScript 與 HTML 之間的交互是通過事件實...
    悶油瓶小張閱讀 286評論 0 0
  • 事件流 IE和Netscape開發團隊提出了完全相反的兩種事件流的概念,事件冒泡流和事件捕獲流。 事件冒泡 事件由...
    exialym閱讀 955評論 0 9
  • 生長在小城鎮里的同學,一定深諳鄉野中生活的人們,對大學生的“偏見”。 他們的生活大多是日出而作日落而息,家族的世代...
    明天glimmer閱讀 627評論 0 15