Ext.bind在ExtJS中看不到功能 [英] Ext.bind does not see function in ExtJS
问题描述
我正在尝试修改Portlet示例并将其移植到我们的程序中.代码如下:
I am trying to mod the Portlet example and port it into our program. The code looks like this:
Ext.create('Ext.container.Viewport',{
id: 'app-viewport', //creates viewport
layout: {
type: 'border',
padding: '0 5 5 5' // pad the layout from the window edges
},
onPortletClose: function(portlet) {
this.showMsg('"' + portlet.title + '" was removed');
},
showMsg: function(msg) {
var el = Ext.get('app-msg'),
msgId = Ext.id();
this.msgId = msgId;
el.update(msg).show();
Ext.defer(this.clearMsg, 3000, this, [msgId]);
},
clearMsg: function(msgId) {
if (msgId === this.msgId) {
Ext.get('app-msg').hide();
}
},
items: [{
id: 'app-header',
xtype: 'box',
region: 'north',
height: 40,
html: 'Ext Welcome'
},{
xtype: 'container',
region: 'center',
layout: 'border',
items: [{
id: 'app-options', //Creates the Options panel on the left
title: 'Options',
region: 'west',
animCollapse: true,
width: 200,
minWidth: 150,
maxWidth: 400,
split: true,
collapsible: true,
layout:{
type: 'accordion',
animate: true
},
items: [{
html: content,
title:'Navigation',
autoScroll: true,
border: false,
iconCls: 'nav'
},{
title:'Settings',
html: content,
border: false,
autoScroll: true,
iconCls: 'settings'
}]
},{
id: 'app-portal', //Creates the panel where the portal drop zones are.
xtype: 'mainpanel',
region: 'center',
items: [{
id: 'col-1', //Each column represents a drop zone column. If we add more there are more created and width gets adjusted accordingly
items: [{
id: 'portlet-1',
title: 'Portlet 1',
html: content,
listeners: {
'close': Ext.bind(this.onPortletClose, this)
},{
id: 'portlet-2',
title: 'Portlet 2',
html: content,
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}]
},{
id: 'col-2',
items: [{
id: 'portlet-3',
title: 'Portlet 3',
html: content,
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}]
},{
id: 'col-3',
items: [{
id: 'portlet-4',
title: 'Portlet 4',
html: content,
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}]
}]
}]
}]
});
问题是Ext.bind无法读取onPortletClose
函数,浏览器给了我一个
The problem is that Ext.bind cannot read the onPortletClose
function and the browser gives me a:
Uncaught TypeError: Cannot read property 'apply' of undefined
错误.我检查了堆栈,实际上在Ext.bind(fn,scope)中,fn
是未定义的,因此它无法读取处理程序函数.我的应用程序和该示例之间的区别是,我将其直接添加到JSP的Ext.onReady()
中,而在示例中,所有这些都是通过Ext.apply(this, {...})
添加的.我真的很困惑我尝试了各种头来将范围强制施加在视口上,但Ext.bind()
内部的任何东西似乎都失去了与外部或其他物体的接触.我以前使用过Ext.bind()
,尽管它在initComponent
配置中,但运行良好.这是强制性的吗?如果没有,那是什么问题?
Uncaught TypeError: Cannot read property 'apply' of undefined
error. I checked the stack and essentially in the Ext.bind(fn,scope) the fn
is undefined and thus it cannot read the handler function. The difference between my application and in the example is that I add this directly into a JSP's Ext.onReady()
whereas in the example all of this is added through a Ext.apply(this, {...})
. I'm really confused. I tried all kinds of gimmicks to force the scope on the viewport but it seems that whatever is inside Ext.bind()
loses contact with outside or something. I've used Ext.bind()
before and it went fine although it was inside an initComponent
configuration. Is that mandatory? If no then what is the problem?
推荐答案
在这里(或通常在使用JavaScript或ExtJS时)理解this
的含义很重要.
It is important to understand the meaning of this
here (or in general when working with JavaScript or ExtJS).
在全局上下文中,this
是指全局对象,也称为全局window
变量. Ext.onReady
函数内部就是这种情况:
In a global context, this
refers to the global object, also known as the global window
variable. This is the case inside your Ext.onReady
function:
Ext.onReady(function() {
console.log(this === window);
// -> true
// because this is the global object
});
在对象上下文中,默认情况下 this
引用该函数的所有者对象(存在多种方法,而实际上这正是您想要使用Ext.bind
实现的):
In an object context, by default this
refers to the owner object of the function (there are ways around it and actually this is exactly want you want do achieve using Ext.bind
):
var obj = {
prop: 'My text property',
fn: function() {
console.log(this.prop);
// -> My text property
// because "this" refers to our object "obj"
}
};
现在,这正是使您的案例与示例中的案例有所不同的原因.
Now, this is exactly what makes the difference between your case and the one from the examples.
将方法与Ext.onReady
和this
一起使用时-如上文所指出-将引用全局对象,该对象当然不具有函数onPortletClose
.
When using the approach with Ext.onReady
this
- as pointed out above - will refer to the global object, which of course does not have a function onPortletClose
.
使用示例中的方法时,this
是从initComponent
内部访问的,该内部函数是派生的视口类的成员函数,因此this
引用组件实例(=拥有的对象) ,这使您可以访问功能.
When using the approach from the examples, this
is accessed from inside of initComponent
, which is a member function of your derived viewport class, and therefore this
refers to the component instance (= the owning object), which allows you to access your function.
Ext.define('MyViewport', {
extend: 'Ext.container.Viewport',
onPortletClose: function(portlet) {
this.showMsg('"' + portlet.title + '" was removed');
},
initComponent: function() {
console.log(this);
// -> the instance of your viewport class
Ext.apply(this, {
items:[{
xtype: 'panel',
title: 'Portlet 1',
listeners: {
'close': Ext.bind(this.onPortletClose, this)
}
}]
});
this.callParent();
}
});
旁注
Ext.apply
Ext.apply
只是将所有属性从一个对象复制到另一个对象,因此在这种情况下,这只是通过一个函数调用将该对象的所有属性应用到this
的便捷方法.您也可以使用:
Side notes
Ext.apply
Ext.apply
really just copies all properties from one object to another, so in this case it is just a convenient way of applying all attributes of that object to this
with one function call. You could as well just use:
this.items = [...];
改变听众的范围
向组件添加侦听器时,无需使用Ext.bind
,只需在listeners
对象中提供scope
配置:
Changing the scope of your listeners
You do not need to use Ext.bind
when adding listeners to a component, you can simply provide a scope
configuration in your listeners
object:
listeners: {
close: function() {...},
scope: this
}
外部来源
如果您想更深入地学习(我建议这样做),您可能想在 查看全文