使用原生JavaScript實現的EventEmitter

和Nodejs 中EventEmitter功能類似.適合瀏覽器自定義事件類.新添加了可以定製事件促發次數的功能.

詳細見

https://github.com/webery/ajax/tree/master

包括了源代碼和測試代碼.未經過嚴格測試,暫時爲第一個版本.還有很多優化的地方,現在只是一個參考.


使用方法

前端測試文件:emit.ejs

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
	<script type="text/javascript" src="/javascripts/eventemitter.js"></script>
  </head>
  <body>
    <input type="button" id="submit" value="click">
  </body>
  <script type="text/javascript">
     document.getElementById('submit').onclick = function() {
	 /*
	    var emit = new EventEmitter();
		
		emit.on('click', function() {
		  console.log('clcik');
		}, 2);
		emit.trigger('click');
		emit.trigger('click');
		emit.trigger('click');
	 */
	 var Target = function(){};
	 EventEmitter.inherit(Target);
	 var test = new Target();
	  test.on('click', function() {
		  console.log('clcik');
		}, 2);
		 test.trigger('click');
		 test.trigger('click');

	 };
  </script>
</html>


源代碼:eventemitter.js

/**
   author:weber yang
   2015.7.31
   瀏覽器端模擬EventEmitter的實現,拓展了部分功能,添加了定製實踐促發的次數的功能,
   使用方式和其他的EventEmiiter類似。
**/
;(function (window, undefined) {
	'use strict';
	/*構造函數*/
	var EventEmitter = function() {
		this.events = {};//保存事務,存儲結構爲{'eventName1':[{listener:function觸發的函數, time:觸發的次數}], 'eventName2':[],}
	};
	
	EventEmitter.prototype.once = function(evt, listener) {
		 return this.addListener(evt, listener, 0);
	};
	/*獲取所有的事務*/
	EventEmitter.prototype.getEvents = function() {
		return this.events || (this.events = {});
	}
	/*獲取某個實踐的所有觸發函數*/
	EventEmitter.prototype.getListeners = function(evt) {
		 var events = this.getEvents();
		 return events[evt] || (events[evt] = []);
	};
	/**
	  註冊實踐觸發函數
	  evet:事件名稱
	  listener:事件監聽函數
	  time:可選,選擇可以觸發的次數,-1表示無數次,默認爲-1
	**/
	EventEmitter.prototype.on = function(evt, listener, time) {
		time = typeof(time) == 'number' ? time : -1;
		time = time >= -1 ? time : -1; 
		var listeners = this.getListeners(evt);
		var listenerWrapper = {
			listener:listener,
			time:time,
		};
		listeners.push(listenerWrapper);
		
        return this;
	};
	/*addListener 和on 同義 */
	EventEmitter.prototype.addListener = EventEmitter.prototype.on;
	/*移除事件的所有監聽函數*/
	EventEmitter.prototype.off = function(evt) {
		var events = this.getEvents();
		events[evt] = [];
	};
	EventEmitter.prototype.removeEvent = EventEmitter.prototype.off;
	
	/**
	  會刪除同一事件中的所有listener
	**/
	EventEmitter.prototype.removeListener = function(evt, listener) {
		var listeners = this.getListeners(evt);
		for(var i=0; i<listeners.length; i++) {
			if(listeners[i].listener == listener) {
				delete listeners[i];
			}
		}
	};
	/**
	  觸發事件
	**/
	EventEmitter.prototype.trigger = function(evt, args) {
		var listeners = this.getListeners(evt);
		for(var i=0; i<listeners.length; i++){
			var listener = listeners[i];
			if(listener.time != -1) {
				listener.time--;
			}
			if (listener.time == 0) {
				this.removeListener(evt, listener.listener);//可以同步或異步執行
			}
			listener.listener.apply(this, args || []);
		}
	};
	EventEmitter.prototype.fire = EventEmitter.prototype.trigger;
	/**
	  觸發事件
	**/
	EventEmitter.prototype.emit = function(evt) {
        var args = Array.prototype.slice.call(arguments, 1);
        return this.trigger(evt, args);
    };
	
	EventEmitter.inherit = function(target) {
		
		if(typeof(target.prototype) == 'undefined') {
			throw 'target:' + target + 'must have prototype';
		}
		var souPto = EventEmitter.prototype;
		var tarPto = target.prototype;
		for(var key in souPto) {
			tarPto[key] = souPto[key];
		}
		return target;
	};
	
	window.EventEmitter = EventEmitter;
	
})(window);
    


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章