使用事件
Ext JS中的组件和类可以在它们生命周期中的各种触发点上有大量的事件可供触发。事件允许你对程序中的改变作出反应。它们是Ext JS中的一个核心概念。
事件是什么
当你类中的某些相关的事情发生时,事件即被触发。例如,当Ext.Component渲染到屏幕时,Ext JS会在渲染完成后触发一个事件。我们可以通过配置一个简单的listeners对象来监听那个事件。
Ext.create('Ext.Panel', {
html: 'My Panel',
renderTo: Ext.getBody(),
listeners: {
afterrender: function() {
Ext.Msg.alert('Success!', 'We have been rendered');
}
}
});
在此示例中,当Panel被渲染到屏幕时,紧接着就会弹出警告信息。一个类中所有可以被触发的事件都在API页面中的events列表里列出来啦-例如,Ext.panel.Panel目前有45个事件。
监听事件
尽管Ext.Component的afterrender事件在某些情况下是有用的,但你或许用得更多的是其它事件。例如,Ext.button.Button被点击时会触发click事件。
Ext.create('Ext.Button', {
text: 'Click Me',
renderTo: Ext.getBody(),
listeners: {
click: function() {
Ext.Msg.alert('Success!', 'I was clicked!');
}
}
});
一个组件可以包含任意多的事件监听器,只要你需要它们。在下面的示例中,我们将在mouseover事件监听器中调用this.hide()方法来隐藏一个按钮。一秒过后,我们又会显示该按钮。当this.hide()被访问,按钮就会隐藏,然后hide事件会被触发。hide事件触发了我们的hide监听器,在监听器里,我们执行代码让按钮在一秒后显示:
Ext.create('Ext.Button', {
renderTo: Ext.getBody(),
text: 'My Button',
listeners: {
mouseover: function() {
this.hide();
},
hide: function() {
// Waits 1 second (1000ms), then shows the button again
Ext.defer(function() {
this.show();
}, 1000, this);
}
}
});
每一次当事件被触发时,事件监听器相应的函数会被访问。所以,你可以继续隐藏或显示按钮,只要你想要这样做。
稍后添加监听器
在前面的示例中,当类实例化时,我们向组件中传入了listeners(监听器)。然而,如果我们已经创建了一个实例,我们可以使用on函数向里面添加监听器。
var button = Ext.create('Ext.Button', {
renderTo: Ext.getBody(),
text: 'My Button'
});
button.on('click', function() {
Ext.Msg.alert('Success!', 'Event listener attached by .on');
});
你也可以通过.on声明多个监听器,就跟使用listener配置项一样。下面的示例使用mouseover事件重新设置了前面示例中的button的可见性。
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);
}
});
移除监听器
我们既然可以在任何时间添加监听器,当然也可以移除他们。这次我们使用un函数。要移除一个监听器,我们需要这个函数的引用。在前面的示例中,我们传入一个函数到监听器对象或者使用on函数。这次我们提前创建一个函数,并把它链接到一个叫做doSomething的变量上,这个变量包含了我们的自定义函数。因为我们在最初就传入了新的doSomething函数到我们的监听器对象,代码跟前面的一样。通过使用Ext.defer函数,在前三秒点击按钮会产生一个提示信息。然而,3秒过后,监听器移除了,因此什么也不会发生。
var doSomething = function() {
Ext.Msg.alert('Success!', '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);
监听范围选项
在你的处理函数中,scope选项设置了监听范围。默认情况下,监听范围被设置为触发此事件的实例对象。虽然大多数情况下使用默认值,但有时你可能需要别的设置。在此指南的前面的第二个示例中,这项功能让我们能够访问this.hide()函数来隐藏按钮。在下面的示例中,我们创建了一个按钮和一个面板。然后用Panel(面板)范围的处理函数监听按钮的click事件。为了达到这个目的,我们需要传入一个对象,而非一个处理函数。这个对象包含了处理函数和范围对象:
var panel = Ext.create('Ext.Panel', {
html: 'Panel HTML'
});
var button = Ext.create('Ext.Button', {
renderTo: Ext.getBody(),
text: 'Click Me'
});
button.on({
click: function() {
Ext.Msg.alert('Success!', this.getXType());
},
scope: panel
});
如果你不太喜欢简短的声明方式,你也可以将代码写长一点。
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('Success!', this.getXType());
}
}
});
当你运行这个示例,点击事件处理函数中的this指向Panel。为了看到所演示的效果,我们弹出了范围组件的xtype。当按钮被点击,我们将看到面板的xtype被弹出来。
监听一次事件
或许有进你想要只监听事件一次。事件本身可能会被触发很多次,但我们只想要它监听一次。下面的代码演示了这种情况:
var button = Ext.create('Ext.Button', {
renderTo: Ext.getBody(),
text: 'Click Me',
listeners: {
click: {
single: true,
fn: function() {
Ext.Msg.alert('Success!', 'I will say this only once');
}
}
}
});
使用缓冲设置
对于事件连续被调用很多次的情况,我们可以通过使用一个buffer配置项来减少监听器的调用次数。在这个示例中,我们的按钮的点击事件监听器只会每两秒钟被调用一次,而不管你在两秒钟内点击它多少次:
var button = Ext.create('Ext.Button', {
renderTo: Ext.getBody(),
text: 'Click Me',
listeners: {
click: {
buffer: 2000,
fn: function() {
Ext.Msg.alert('Success!', 'I say this only once every 2 seconds');
}
}
}
});
触发自定义事件
通过访问fireEvent方法并传入一个事件名称可以触发你自己的事件。在下面的示例中,我们触发了一个叫做myEvent的事件,并在处理函数中传入两个参数 – 按钮本身和一个1到100的随机数字:
var button = Ext.create('Ext.Button', {
renderTo: Ext.getBody(),
text: "Just wait 2 seconds",
listeners: {
myEvent: function(button, points) {
Ext.Msg.alert('Success!', 'myEvent fired! You score ' + points + ' points');
}
}
});
Ext.defer(function() {
var number = Math.ceil(Math.random() * 100);
button.fireEvent('myEvent', button, number);
}, 2000);
我们又一次使用Ext.defer来延迟触发我们自定义事件的函数的执行,这一次,我们延迟了2秒。当事件被触发时,myEvent监听器与对应的处理函数关联并执行,显示出我们传入的参数。
监听DOM事件
并非每个ExtJS组件都能触发所有事件。然而,通过定位到容器的元素,我们可以为很多原生的可以被组件监听的事件注册处理函数。在此示例中,我们定位Ext.container.Container。容器并没有click事件。让我们给它一个!
var container = Ext.create('Ext.Container', {
renderTo: Ext.getBody(),
html: 'Click Me!',
listeners: {
click: function(){
Ext.Msg.alert('Success!', 'I have been clicked!')
}
}
});
container.getEl().on('click', function(){
this.fireEvent('click', container);
}, container);
如果没有第二段代码,容器的click监听器不会被触发。因为我们定位到了容器的元素,然后给它加了一个点击的监听器,我们已经扩展容器的事件功能。
事件标准化
事件的标准化是让Ext JS 5版本及以上的程序能够在触屏设备上运行的关键所在。这种标准化是在场景后发生,并且从标准的鼠标事件转化到与他们相关的触摸与指针事件是相当简单的转化。
指针事件是标准的w3c规范,用来处理屏幕上的一套坐标体系,不管是何种输入装备(鼠标,触摸,触笔等等)
小姑娘你的代码注册一个鼠标事件的监听器,框架会根据需要附加对应的触摸与指针事件。例如,如果程序要注册一个mousedown监听器:
myElement.on('mousedown', someFunction);
在设备支持触摸事件的情况下,事件系统会将此转换为touchstart事件:
myElement
.on('touchstart',someFunction
);
或者在设备支持指针事件的情况下,转化为pointerdown事件:
myElement
.on('pointerdown',someFunction
);
这处转化会在适当的情况下自动进行,所以不需要写额外的代码就能够支持平板电脑与触摸设备。转化可以通过用translate事件选项来禁用掉:
myElement.on({
mousedown: someFunction,
// only listen to mousedown. Do not call the handler in response to touchstart or pointerdown.
translate: false
});
更多的事件
除了DOM元素事件和组件事件,ExtJS还提供了一个强有力的系统用来识别有意义的手势。比如捏(pinch),旋转(rotate),拖拽(drag)等等。更多关于这些事件的信息,请查看手势指南篇章(http://docs.sencha.com/extjs/6.2.1/guides/core_concepts/gestures.html)。