我正在尝试修改 Portlet 示例并将其移植到我们的程序中。代码如下所示:
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
函数,浏览器给我一个:
未捕获类型错误:无法读取未定义的属性“应用”
错误。我检查了堆栈,基本上在 Ext.bind(fn,scope) 中,fn
未定义,因此它无法读取处理程序函数。我的应用程序与示例中的区别在于,我将其直接添加到 JSP 的 Ext.onReady()
中,而在示例中,所有这些都是通过 Ext.apply(this, {...})
。我真的很困惑。我尝试了各种花招来强制视口(viewport)上的范围,但似乎 Ext.bind() 内部的任何内容都与外部或其他东西失去了联系。我之前使用过 Ext.bind() ,尽管它位于 initComponent
配置内,但运行良好。这是强制性的吗?如果不是那么问题是什么?
最佳答案
理解这里的 this
的含义(或者一般在使用 JavaScript 或 ExtJS 时)非常重要。
在全局上下文中,this
指的是全局对象,也称为全局window
变量。这是 Ext.onReady
函数内的情况:
Ext.onReady(function() {
console.log(this === window);
// -> true
// because this is the global object
});
在对象上下文中,默认 this
指的是函数的所有者对象(有很多方法可以解决它,实际上这正是您想要使用来实现的) Ext.bind
):
var obj = {
prop: 'My text property',
fn: function() {
console.log(this.prop);
// -> My text property
// because "this" refers to our object "obj"
}
};
现在,这正是您的案例与示例中的案例之间的区别。
当使用 Ext.onReady
方法时,this
- 如上所述 - 将引用全局对象,该对象当然没有函数 onPortletClose
.
使用示例中的方法时,从 initComponent
内部访问 this
,它是派生视口(viewport)类的成员函数,因此 this
指的是组件实例(= 所属对象),它允许您访问您的函数。
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
实际上只是将所有属性从一个对象复制到另一个对象,因此在本例中,这只是一种通过一次函数调用将该对象的所有属性应用到this
的便捷方法。您也可以使用:
this.items = [...];
更改监听器的范围
向组件添加监听器时不需要使用 Ext.bind
,只需在 监听器
中提供 scope
配置即可对象:
listeners: {
close: function() {...},
scope: this
}
外部来源
如果您想更深入地了解(我推荐),您可能需要在 MDN (Mozilla Developer Network) 阅读有关此的更多信息。 .
关于javascript - Ext.bind 在 ExtJS 中看不到函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24913743/