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');
});
- 三种绑定事件的方式
- Ext.EventManager.on(el, ename, fn);
- Ext.EventManager.on(el, {ename1:fn1, ename2:fn2});
- 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!');
}
}
});
}
标签:function,inp,alert,eventName,Ext,事件,机制,fn 来源: https://blog.csdn.net/SUNBOYmxbsH/article/details/112094657