摘要:首先來看看什么是自定義事件讓函數能夠具備事件的某些特性。其實自定義事件在一些主流的類庫中都有實現,后續會分析具體的實現方法。今天,我們就先用簡單的例子來實現自定義事件的功能。
在團隊協作的很多情況下,某個js的函數會根據不斷增加的需求進而不斷增加功能,如果功能需求累積過多,我們就很難把控自己在這個函數中新定義的變量會不會覆蓋掉之前的定義。如:
function action(){ console.log(1); console.log(2);//新增需求1 console.log(3);//新增需求2 ......//一直增加就很難保證下面的代碼不會與之前的代碼產生沖突 }
而如果我們為新增的需求重新定義一個同名的js方法,那后來定義的方法又會將之前定義的方法覆蓋,這當然也不是我們想要的結果。如:
function action(){console.log(1);} function action(){console.log(2);}//新增需求1 function action(){console.log(3);}//新增需求2
執行結果:3
那么有沒有什么辦法可以讓我們的函數分別執行,并且互不影響呢?是的,你一定想到了js事件。
說到js的事件,我們立馬就會想到原生js中對事件的實現。在標準DOM瀏覽器中的addEventListener、removeEventListener和在IE中的attachEvent、detachEvent這些已經為我們熟知,并且綁定在同一個DOM中的相同的事件彼此不會被覆蓋,比如,你在某個div中綁定了3個click事件,在執行時它們會按序執行,而不會只執行最后一次綁定:
//下面的例子僅實現標準DOM瀏覽器 oDiv.addEventListener("click",function(){console.log(1);},false); oDiv.addEventListener("click",function(){console.log(2);},false); oDiv.addEventListener("click",function(){console.log(3);},false);
執行結果:1 2 3
看起來剛好解決了我們的各種顧慮,多帶帶定義,互不影響,很有利于團隊協作,但是這些內置的事件綁定方式卻依然無法直接解決我們的問題。
好吧,既然無法直接解決,那我們就利用頁面事件綁定的思想來自己探索,這就是我們今天要介紹的自定義事件。
首先來看看什么是自定義事件:讓函數能夠具備事件的某些特性。
其實自定義事件在一些主流的類庫中都有實現,后續會分析具體的實現方法。今天,我們就先用簡單的例子來實現自定義事件的功能。
回到開始的時候我們提出的需求:讓函數分別執行,并且互不影響。這就好像我們要按照清單從圖書館借5本書,走出圖書館的時候,我們手里拿到的應該是想借的5本,而不是清單上的最后一本。
依照js的事件綁定方式來剖析一下這幾本書和圖書館之間的關系:
其中,圖書館就是我們要綁定事件的對象,也就是我們借書的對象,“click”就是我們綁定事件的類別,也就是我們想要借的書的分類,而function回調就是我們要執行的函數,也就是我們想借的具體某本書。理清了對應關系,我們就可以從一個圖書館內不同的分類書架上拿到不同的書。
把這個對應的關系映射到自定義事件上就是:在某個對象上綁定不同類別的一個或多個方法,并且讓它們分別執行。接下來我們就來實現一下這種關系。首先來看一下自定義事件的綁定實現:
//綁定 function on(obj,events,fn){//參數分別是:對象/自定義事件類別/方法 //初始化自定義監聽對象,如果存在繼續使用,不存在就創建新對象 obj.listeners = obj.listeners || {}; obj.listeners[events] = obj.listeners[events] || [];//初始化監聽的自定義事件列表 obj.listeners[events].push(fn);//將要執行的方法分別存放到對應事件的列表中 }
這樣,我們就把想要執行的一系列方法綁定到了某個頁面對象對應的自定義事件類別上。方法綁定好了之后,如何去觸發呢?看下面的代碼實現:
//觸發 function fire(obj,events){//參數分別是:對象/自定義事件類別 for(var i = 0; i < obj.listeners[events].length; i++){//遍歷某個事件類別下所有的方法 obj.listeners[events][i]();//依次執行遍歷到的所有的方法 } }
這樣,我們定義的想要去執行的每個方法都能被執行,并且它們之間互不影響??磦€實際的例子:
var eventHandle = { on: function(obj,events,fn){ obj.listeners = obj.listeners || {}; obj.listeners[events] = obj.listeners[events] || []; obj.listeners[events].push(fn); }, fire: function(obj,events){ for(var i = 0, n = obj.listeners[events].length; i < n; i++){ console.log(obj.listeners[events]); obj.listeners[events][i] && obj.listeners[events][i](); } }, off: function(obj,events){ for(var i = 0, n = obj.listeners[events].length; i < n; i++){ obj.listeners[events][i] = null; } } }; //綁定自定義事件, eventHandle.on(oDiv,"eventType1",function(){console.log(1);});//準備執行方法1 eventHandle.on(oDiv,"eventType1",function(){console.log(2);});//準備執行方法2 eventHandle.on(oDiv,"eventType1",function(){console.log(3);});//準備執行方法3 eventHandle.on(oDiv,"eventType2",function(){console.log(4);});//準備執行方法4 //觸發執行 eventHandle.fire(oDiv,"eventType1");//執行eventType1下的所有方法
執行結果:1 2 3
不執行方法4是因為,eventType2下的方法4僅僅被綁定,并沒有被觸發。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/86165.html
摘要:它有發布者,訂閱者這兩個主要對象。的最佳實踐就是通過反射犧牲了微小的性能,同時極大的降低了程序的耦合度。官網和應用場景框架的主要功能是幫助我們來降低多個組件通信之間的耦合度的解耦。 前兩天在公眾號里發了一篇有關EventBus的文章《玩轉EventBus,詳解其使用》,有讀者和開發者反饋說沒有OTTO好用。確實是,各有優缺點吧,那今天就有必要再講一下Otto事件框架。 OTTO是Squ...
摘要:調用棧是一種棧結構它用來存儲計算機程序執行時候其活躍子程序的信息。調用棧是解析器的一種機制。并形成一個棧幀任何被這個函數調用的函數會進一步添加到調用棧中,形成另一個棧幀并且運行到它們被上個程序調用的位置。然后調用棧繼續運行其他部門。 大家在進行javascript開發的時候,有沒有想過,我們寫的代碼是怎么樣運行的呢?下面我們就來剖析一下代碼的執行過程。 一 什么是調用棧 代碼在運行過程...
閱讀 1990·2021-09-07 10:24
閱讀 2092·2019-08-30 15:55
閱讀 2046·2019-08-30 15:43
閱讀 674·2019-08-29 15:25
閱讀 1061·2019-08-29 12:19
閱讀 1940·2019-08-23 18:32
閱讀 1522·2019-08-23 17:59
閱讀 952·2019-08-23 12:22