ie7、ie8相容addEventListener和removeEventListener,解決this指向和detachEvent解除綁定事件問題

来源:http://www.cnblogs.com/duanhaochen/archive/2016/10/15/5965641.html
-Advertisement-
Play Games

現代瀏覽器監聽事件使用addEventListener函數,解除綁定監聽使用removeEventListener函數。但是ie7、ie8監聽事件使用attachEvent函數,解除監聽事件使用detachEvent函數。 簡單的相容函數: addEventListener綁定的監聽事件,事件內th ...


現代瀏覽器監聽事件使用addEventListener函數,解除綁定監聽使用removeEventListener函數。但是ie7、ie8監聽事件使用attachEvent函數,解除監聽事件使用detachEvent函數。

簡單的相容函數:

1 if(document.addEventListener){
2     element.addEventListener(type, fun, useCapture);
3 }else{
4     element.addEventListener("on" + type, fun);
5 }

 

addEventListener綁定的監聽事件,事件內this指向element。但是attachEvent綁定的監聽事件,事件內this指向window,使用call或者apply可以解決該問題,修改this指向element,event作為參數傳遞。

 1 var addListener = (function(){
 2     if(document.addEventListener){
 3         return function(element, type, fun, useCapture){
 4             element.addEventListener(type, fun, useCapture ? useCapture : false);
 5         };    
 6     }else{
 7         return function(element, type, fun){
 8             element.attachEvent("on" + type, function(event){
 9                 fun.call(element, event);
10             });
11         };
12     }
13 })();

 

但是這樣也有個問題,就是detachEvent無法解除監聽,因為傳遞的事件已經改變了。通過function.prototype將修改後的函數和已經綁定該事件的dom儲存起來,可以使detachEvent時能獲取到解除監聽的函數,addEventListener自己會避免多次綁定一個事件,attachEvent需要自己判斷是否綁定多次事件。

 1 /**
 2  * addEventlistener相容函數
 3  * ie9以上正常使用addEventlistener函數
 4  * ie7、ie8用傳遞的function的function.prototype儲存經過處理的事件
 5  * function.prototype["_" + type]:記錄處理後的信息
 6  * function.prototype["_" + type]._function <function>:經過處理的事件
 7  * function.prototype["_" + type]._element  <array>   :已經綁定的dom
 8  */
 9 
10 /*** addEventlistener ***/
11 var addListener = (function(){
12     if(document.addEventListener){
13         /* ie9以上正常使用addEventListener */
14         return function(element, type, fun, useCapture){
15             element.addEventListener(type, fun, useCapture ? useCapture : false);
16         };
17     }else{
18         /* ie7、ie8使用attachEvent */
19         return function(element, type, fun){
20             if(!fun.prototype["_" + type]){
21                 /* 該事件第一次綁定 */
22                 fun.prototype["_" + type] = {
23                     _function: function(event){
24                         fun.call(element, event);
25                     },
26                     _element: [element]
27                 };
28                 element.attachEvent("on" + type, fun.prototype["_" + type]._function);
29             }else{
30                 /* 該事件被綁定過 */
31                 var s = true;
32                 // 判斷當前的element是否已經綁定過該事件
33                 for(var i in fun.prototype["_" + type]._element){
34                     if(fun.prototype["_" + type]._element[i] === element){
35                         s = false;
36                         break;
37                     }
38                 }
39                 // 當前的element沒有綁定過該事件
40                 if(s === true){
41                     element.attachEvent("on" + type, fun.prototype["_" + type]._function);
42                     fun.prototype["_" + type]._element.push(element);
43                 }
44             }
45         };
46     }
47 })();
48 /*** removeEventlistener ***/
49 var removeListener = (function(){
50     if(document.addEventListener){
51         /* ie9以上正常使用removeEventListener */
52         return function(element, type, fun){
53             element.removeEventListener(type, fun);
54         };
55     }else{
56         /* ie7、ie8使用detachEvent */
57         return function(element, type, fun){
58             element.detachEvent("on" + type, fun.prototype["_" + type]._function);
59             if(fun.prototype["_" + type]._element.length === 1){
60                 // 該事件只有一個element監聽,刪除function.prototype["_" + type]
61                 delete fun.prototype["_" + type];
62             }else{
63                 // 該事件只有多個element監聽,從function.prototype["_" + type]._element數組中刪除該element
64                 for(var i in fun.prototype["_" + type]._element){
65                     if(fun.prototype["_" + type]._element[i] === element){
66                         fun.prototype["_" + type]._element.splice(i, 1);
67                         break;
68                     }
69                 }
70             }
71         };
72     }
73 })();

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 子元素避免同時使用float和margin。 如: 需要子元素的margin-bottom:20px時,可以給用父元素設置padding-bottom:20px代替。 ...
  • 1.meta標簽。 1.1 <meta charset="utf-8"> charset:字元集 1.2 <meta name="keywords" content=""> 作用:對網站進行優化的作用 SEO 提高排名。 1.3 <meta name="description" content="" ...
  • 作為web前端初學者,今天要記錄的是三個控制項的使用心得,分別是表格控制項jqgrid,樹形控制項ztree,圖表控制項echarts。下邊分別進行描述。 1.jqgrid 首先放官方demo網站上來,http://blog.mn886.net/jqGrid/,上面的描述還是挺有幫助的。 jqgrid的添加 ...
  • 每學習一些新的東西,要學會複習,總結和記錄。 今天來簡單總結一下學到的幾個事件:焦點事件、Event事件對象、冒泡事件 其實這幾個事件應該往深的說是挺難的,但今天主要是以一個小菜的角度去嘗試理解一些基本的知識點。 1.焦點事件: 1.1概念理解: 想象場景:當一堆text文本框出現在面前,當點擊其中 ...
  • JavaScript中有一些名字十分冗長的函數名稱,導致使用時會混亂,特此整理一番,加深印象。 ①Object.getOwnPropertyDescriptor ——讀取某個對象特定屬性的屬性描述符(value / writable / enumerable / configurable) 這個方法 ...
  • SVG的畫布、畫布視區(viewBox)、瀏覽器視窗的概念 畫布 畫布是繪製SVG內容的一塊區域,理論上在所有維度上都是無限的。(也有人稱為“SVG世界”,但我覺得叫畫布比較合適) 畫布視區(viewBox) 就是截取畫布某一塊矩形區域作為顯示的區域。(有人也稱為“視野”或“視區盒子”,但我覺得不夠 ...
  • 由於前端是不能直接操作本地文件的,要麼通過<input type="file">用戶點擊選擇文件或者拖拽的方式,要麼使用flash等第三方的控制項,但flash日漸衰落,所以使用flash還是不提倡的。同時html5崛起,提供了很多的api操控,可以在前端使用原生的api實現圖片的處理,這樣可以減少後 ...
  • 一、javascript原型認識 很多編程語言都有類的概念,我們可以拿原型和類進行比較,看看它們之間的區別以及相同點在哪裡。 1、類:類是一個具體事物的抽象所以類是一個抽象的東西,在面向對象中類可以用來構造對象,這就是一個抽象—具體的過程。在現實生活中就好比:圖紙造汽車。 2、原型:javascri ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...