Extjs5之事件(Events)

事件驱动编程:为需要处理的事件编写相应的事件处理程序,代码在事件发生时执行。extjs是基于事件(Events)来响应用户操作的,extjs的事件分布在组件和类的生命周期的不同点上,事件让你的代码在程序状态发生改变的时候做出响应。 事件是extjs的一个重要概念。

1.什么是事件

有些时候我们需要在事件触发时做一些事情。例如,当Ext.Component呈现到屏幕上,Ext JS的渲染完成之后触发一个事件。我们可以通过配置侦听事件的一个简单的监听器对象来实现:
[code lang=”js”]
Ext.create(‘Ext.Panel’, {
html: ‘My Panel’,
renderTo: Ext.getBody(),
listeners: {
afterrender: function() {
Ext.Msg.alert(‘We have been rendered’);
}
}
});
[/code]
效果图

在这个例子中,一打开网页panel渲染到屏幕,紧接着提示窗口出来了。一个类的所有事件在这个类的api文档中列出来了。例如Ext.panel.Panel就有45个事件。

2.添加事件监听
组件的AfterRender是在某些情况下有用,但是其他事件也是非常有用的。例如,Ext.Button的点击事件:

[code lang=”js”]
Ext.create(‘Ext.Button’, {
text: ‘Click Me’,
renderTo: Ext.getBody(),
listeners: {
click: function() {
Ext.Msg.alert(‘I was clicked!’);
}
}
});
[/code]
运行结果

上面例子中我们实现了一个按钮的点击响应,通常一个组件可以包含多个的事件侦听器。在下面的例子中,在监听到鼠标移进来的事件中我们调用this.hide()来隐藏按钮。然后按钮隐藏一秒钟后我们再一次显示按钮。当this.hide()被调用时,该按钮被隐藏,隐藏事件触发。隐藏事件触发了隐藏侦听器,它会等待一秒钟,再次显示按钮:

[code lang=”js”]
Ext.create(‘Ext.Panel’, {
html: ‘My Panel’,
renderTo: Ext.getBody(),
listeners: {
afterrender: function() {
Ext.Msg.alert(‘We have been rendered’);
}
}
});
[/code]
运行效果

事件监听器在每一个事件被触发时被调用,这样你就可以随心所欲的隐藏和显示的按钮了。

3.延迟绑定事件监听

前面的例子中我们在创建一个控件的时候绑定了事件的监听器,通常我们还可用使用on函数来延迟添加事件的监听器,例如
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘My Button’
});

button.on(‘click’, function() {
Ext.Msg.alert(‘Event listener attached by .on’);
});
[/code]
同样你也可以使用on函数来添加多个事件的监听器,例如前面例子你可以这样实现:
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘My Button’
});

button.on({
mouseover: function() {
this.hide();
},
hide: function() {
Ext.defer(function() {
this.show();
}, 1000, this);
}
});
[/code]
效果是一样的。

4.移除监听器

就像我们可以在任何时候添加监听器,我们也可以将其删除。这次我们要使用功能是删除一个监听器,要删除一个监听器我们需要得到引用它的控件。在前面的例子中,我们实现了一个按钮的点击事件监听。这一次,我们实现了之前的功能,并将其保存到一个名为doSomething的变量,它包含了我们的自定义函数。最初我们在创建控件的时候绑定doSomething到click事件中,随后我们通过defer方法延迟3秒后将doSomething移除。效果是刚才开始我们点击按钮会弹出一个提示框,三秒后点击就什么反应都没了。
[code lang=”js”]
var doSomething = function() {
Ext.Msg.alert(‘listener called’);
};

var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘My Button’,
listeners: {
click: doSomething,
}
});

Ext.defer(function() {
button.un(‘click’, doSomething);
}, 3000);
[/code]

5.配置监听器的作用域(Scope)

Scope是事件处理函数的一个内置属性,默认情况下Scope的值是当前控件。但是有些时候我们要实现某些特别的功能需要修改他的Scope,比如我们稍微改动一下前面的例子,我们将按钮的Scope设置为我们创建的panel,然后在点击的时候显示出当前的xtype。
[code lang=”js”]
var panel = Ext.create(‘Ext.Panel’, {
html: ‘Panel HTML’
});

var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘Click Me’
});

button.on({
click: {
scope: panel,
fn: function() {
Ext.Msg.alert(this.getXType());
}
}
});
[/code]
运行效果:

从运行效果我们看看到打印处理的xtype是panel,这说明了事件的作用域已经被改变。

6.只响应一次事件

有些时候我们对一个事件的响应只需要响应一次,但是这个事件有可能会被多次触发,下面的代码可以实现我们的需求:
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘Click Me’,
listeners: {
click: {
single: true,
fn: function() {
Ext.Msg.alert(‘I will say this only once’);
}
}
}
});
[/code]

7.配置缓冲器(消抖)

有些事件在短时间内被触发多次,我们可以通过配置一个缓冲器的缓冲次数。在这种情况下我们的按钮的click侦听器两秒内只调用一次,不管你有多少次点击它,代码如下
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: ‘Click Me’,
listeners: {
click: {
buffer: 200,
fn: function() {
Ext.Msg.alert(‘I say this only once every 2 seconds’);
}
}
}
});
[/code]

8.制定自定义事件

自定义事件可以通过事件名字作为参数调用fireEvent函数来触发,例如下面的例子实现了一个名字为myEvent两个参数的事件,一个参数是按钮本身,一个参数是1到100的随机数:
[code lang=”js”]
var button = Ext.create(‘Ext.Button’, {
renderTo: Ext.getBody(),
text: "Just wait 2 seconds",
listeners: {
myEvent: function(button, points) {
Ext.Msg.alert(‘myEvent fired! You score ‘ + points + ‘ points’);
}
}
});

Ext.defer(function() {
var number = Math.ceil(Math.random() * 100);

button.fireEvent(‘myEvent’, button, number);
}, 2000);
[/code]

我们通过Ext.defer函数延时两秒触发了这个事件。

9.监听dom事件

并不是每一个ExtJS的组件都能引发每个事件,例如容器的元素就没有click事件。我们可以将许多原生事件添加给组件就可以监听了。在这个例子中,我们的目标Ext.Container,容器没有一个click事件,让我们给它实现一个

[code lang=”js”]
var container = Ext.create(‘Ext.Container’, {
renderTo: Ext.getBody(),
html: ‘Click Me!’,
listeners: {
click: function(){
Ext.Msg.alert(‘I have been clicked!’) // This won’t fire without the code below
}
}
});

container.getEl().on(‘click’, function(){
this.fireEvent(‘click’, container);
}, container);
[/code]

如果没有第二块代码,容器的点击监听器将不会触发。我们为容器元素添加了点击监听器,我们增强了容器的事件的能力。

10.事件的统一化

事件统一化是让Ext JS的5应用程序在触摸屏设备上运行的关键。这种统一化发生在幕后,是从标准的鼠标事件的简单翻译为等效的触摸和指针事件。标准的W3C指针事件是一组在屏幕上的坐标,不管输入设备(鼠标,触摸,手写笔等)

当你的代码需要监听鼠标事件,只需要在控件附加一个类似的触摸或指针事件。例如,如果应用程序监听一个鼠标按下监听器:
myElement.on(‘mousedown’, someFunction);
触摸开始:
myElement.on(‘touchstart’, someFunction);
指针按下:
myElement.on(‘pointerdown’, someFunction);

这个翻译很到位,让你可以实现平板电脑和触摸屏的支持,而无需任何额外的编码。
在大多数情况下,该框架可以通过鼠标,触摸和指针输入之间的无缝转换。然而,也有一些鼠标交互(如鼠标悬停),不容易转化为触摸交互。这些事件将需要一个单独的基础上处理,并在下面的章节中讨论。

11.手势

除了标准的DOM事件,元素也实现了“手势”事件。基于Sencha Touch触摸事件系统构成的基础,在Ext JS的5新的事件系统中Sencha Touch用户可能已经熟悉了这个概念。
从浏览器的角度来看,鼠标、触摸、指针也有三个主要的事件包括start, move, 和 end:

通过处理这些事件的顺序和时间,该框架可以合成更复杂的事件,如拖动,轻扫,长按,捏,旋转和点击。 Ext JS的应用程序可以监听手势事件就像其他任何事件,例如长按:
Ext.get(‘myElement’).on(‘longpress’, handlerFunction);

原来Sencha Touch手势系统主要考虑触摸事件来设计。通过增加对指针和鼠标事件的手势系统的全面支持使得Ext JS5可以对任何类型的输入作出响应。这不仅意味着所有的手势可以使用触摸事件触发,而且所有单点手势(点击,拖拉等)可以使用鼠标事件触发。这导致一个手势系统,无缝跨越各种输入不同输入系统的设备。