Ext事件机制

  • 最初的事件处理方式

在早期,不存在事件的概念,开发者用javascript的两个函数来模拟事件机制(window.setTimeout和window.setInterval),由于很多原因,如效率低下等,发明了最原始的0级dom事件模型,为元素添加一个事件,在事件上绑定一个处理函数。
缺点: 这种模型不能为元素的事件添加多个处理函数
例如:

	var inp = document.createElement('input');
	inp.id = 'inp1';
	inp.type = 'button';
	inp.value = '点击';
	// 添加点击事件处理函数
	inp.onclick = function(){
		alert('点击!!!click');
	};
	// 不能添加多个处理函数
//	inp.onclick = function(){
//		alert('点击!!!click2');
//	};
	
	// 渲染到页面
	document.body.appendChild(inp);
  • 标准dom事件模型
    在存在0级事件模型之后,才成立了w3c,感觉0级事件模型不好用,就推出了2级事件模型(即标准dom事件模型)。主要提供了添加事件和移除事件的两个标准方法:
 element.addEventListener(type, listener, useCapture); // 添加事件
 element.removeEventListener(type, listener, useCapture); // 移除事件

使用方式如下:

window.onload = function(){
	var inp = document.createElement('input');
	inp.id = 'inp1';
	inp.value = '点击';
	inp.type = 'button';
	
	
	// type 事件类型
	// listener 为事件绑定的函数
	// useCapure 事件传播 true=捕获  false=冒泡
	inp.addEventListener('click', test1, false);
	inp.removeEventListener('click', test1, false);
	inp.addEventListener('click', test2, false);
	
	// 特殊浏览器 但IE11已经支持w3c标准
	// IE  attachEvent(); detachEvent();
	//	inp.attachEvent('onclick', test1);
	//	inp.attachEvent('onclick', test2);
	
	document.body.appendChild(inp);
};

function test1(){
	alert('test1');
};
function test2(){
	alert('test2');
}
  • 事件的传播机制
    w3c 提供了event事件对象,定义事件的三个阶段: 1捕获 2 目标命中 3 冒泡。
window.onload = function(){
	var inp = document.createElement('input');
	inp.id = 'inp1';
	inp.value = '点击';
	inp.type = 'button';
	
	inp.addEventLisener('click', function(event){
		alert('input execute...');
		event.stopPropagation();//阻止冒泡事件的发生
	}, false);
	
	var div = document.createElement('div');
	div.addEventListener('click', function(){
		alert('div execute...');
	}, false);
	
	document.body.addEventListener('click', function(){
		alert('body execute...');
	}, false);
	
	div.appendChild(inp);
	document.body.appendChild(div);
	
};
  • Ext.EventManager
    Ext.EventManager封装浏览器自带的事件,解决了浏览器的差异问题。
var MyExt = {};

MyExt.EventManager = {
	
	// 添加监听
	addListener:function(element, eventName, fn, useCapture){
		if(element.addEventListener){
			element.addEventListener(eventName, fn, useCapture);
		} else if(element.attachEvent){
			element.attachEvent('on'+eventName, fn);
		}
	},
	
	// 移除监听
	removeListener:function(element, eventName, fn, useCapture){
		if (element.removeEventListener){
			element.removeEventListener(eventName, fn, useCapture);
		} else if (element.detachEvent) {
			element.detachEvent('on'+eventName, fn);
		}
	}
	
};


MyExt.EventManager.on = MyExt.EventManager.addListener;
MyExt.EventManager.un = MyExt.EventManager.removeListener;


window.onload = function(){
	var btn = document.getElementById('btn');
	MyExt.EventManager.on(btn, 'click', function(){
		alert('execute ...');
	}, false);
	
	MyExt.EventManager.on(btn, 'click', function(){
		alert('execute again ...');
	}, false);
};

  • 利用观察者模式实现自定义事件
Ext.onReady(function(){
	 // 利用观察者模式实现自定义事件
	 
	 // 1:由于浏览器自己也可以定义内置事件,如click/blur等,
	 //	我们自己也可以有一个类似的类,并可以在此类中定义一些事件
	 var observable = function(){
	 	// 存储自定义的事件类型
	 	this.events = ['start', 'stop'];
	 	
	 	// 设计一种数据结构,可以维护自定义的事件类型和事件之间的绑定关系,如下:
	 	// 			'start':[fn1, fn2, ...]
	 	// 			'stop':[fn1, fn2, ...]
	 	this.listeners = {};
	 };	
	 
	 
	// 2:添加新的自定义事件类型
	observable.prototype.addEvents = function(eventName){
		this.events.push(eventName);
	};
	 
	// 3:为自己的事件类型绑定响应的函数,添加事件监听
	observable.prototype.addListener = function(eventName, fn){
		// 先判断当前事件类型是否已经存在
		if(this.events.indexOf(eventName) == -1){
			this.addEvents(eventName);//当前不存在时,加入该事件
		}
		
		// 获取事件类型绑定的所有的函数
		var arr = this.listeners[eventName];
		// 如果当前这个函数数组不存在,则需要为此事件类型绑定新添加的函数
		if (!arr) {
			arr = [fn];// 直接绑定函数
		} else {
			// 如果当前事件类型已经存在绑定的函数,则校验所绑定的函数中是否已经包含了要绑定的fn函数
			if (arr.indexOf(fn) == -1){
				arr.push(fn);//如果不包含,则加入当前要绑定的函数
			}
		}
		
		// 重新维护一下当前事件类型所绑定的事件数组的关联关系
		this.listeners[eventName] = arr;
		
	};
	
	// 4:移除事件监听
	observable.prototype.removeListener = function(eventName, fn){
		// 先校验要移除的事件类型是否已经定义
		if (this.events.indexOf(eventName) == -1) {
			return;
		}
		
		// 存在要移除的事件类型时
		// 判断当前事件绑定的函数中是否包含要移除的函数
		var arr = this.listeners[eventName];
		if (!arr) {
			return;
		}
		
		// 判断要移除的函数fn存在与当前事件的函数数组中时
		if (arr.indexOf(fn) != -1) {
			// 要移除的函数存在与事件类型对应的函数
			arr.splice(arr.indexOf(fn), 1);
		}
		
	};
	
	 
	// 5、如何触发事件   即调用这个事件类型所对应的所有函数即可
	observable.prototype.fireEvent = function(eventName){
		// 如果没有传递事件类型,或者当前传递的事件类型不存在,则直接返回
		if (!eventName || this.events.indexOf(eventName) == -1) {
			return;
		}
		
		// 存在对应事件
		var arr = this.listeners[eventName];
		if (!arr) {
			return;
		}
		
		for(var i=0, len=arr.length; i<len; i++){
			var fn = arr[i];
			fn.call(fn, this);
		}
		
	};
	 
	// 6、javascript习惯  为原型对象方法起一个简单的名称,方便开发者使用
	observable.prototype.on = observable.prototype.addListener;
	observable.prototype.un = observable.prototype.removeListener;
	observable.prototype.fr = observable.prototype.fireEvent;
	
	
	//测试
	var ob = new observable();
	var fn1 = function(){
		alert('fn1...');
	};
	ob.on('start', fn1);
	
	var fn2 = function(){
		alert('fn2...');
	};
	ob.on('stop', fn2);
	
	// 移除监听
	//ob.un('start', fn1);
	
	ob.fr('start');
	ob.fr('stop');

	
	// 添加新事件
	ob.on('run', function(){
		alert('run');
	});
	
	ob.fr('run');
	
});
  • 三种绑定事件的方式
  1. Ext.EventManager.on(el, ename, fn);
  2. Ext.EventManager.on(el, {ename1:fn1, ename2:fn2});
  3. Ext.EventManager.on(el, {ename1:{fn:fun}, ename2:{fn:fun}});
Ext.onReady(function(){
	var inp = document.createElement('input');
	inp.type = 'button';
	inp.id = 'inp1';
	inp.value = '点击';
	document.body.appendChild(inp);
	
	var extInp = Ext.get('inp1');

	Ext.EventManager.on(extInp, 'click', function(){
		alert('execute  ...');
	});
	Ext.EventManager.on(extInp, 'click', function(){
		alert('execute again ...');
	});
	
	//	绑定多个事件:方式一
	Ext.EventManager.on(extInp, {
		'click':function(){
			alert('单击!');
		},
		'mouseout':function(){
			alert('移除!');
		}
	});

	//	绑定多个事件:方式二
	Ext.EventManager.on(extInp, {
		'click':{
			fn:function(){
				alert('点击1!');
			}
		},
		'mouseout':{
			fn:function(){
				alert('点击2!');
			}
		}
	});

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值