![](/img/trans.png)
[英]ExtJs 6.0 - Javascript event handler function scope inside Ext.application
[英]Scope in ExtJS 4 inside a function handler
我已经对范围问题进行了一些搜索,发现了一些东西,但我不确定它们是否适用于我的情况。 我真的很困惑,所以我想我不妨直接问论坛。
我有一个树面板。 在该树面板中,我有一个xtype的dockedItem:'textfield'。 该textfield接受一个值,并通过在特殊键事件的处理程序内的Ext.Ajax.Request将其用作ajax请求中的参数。 服务器在其响应上返回一个JSON对象,该对象将被解码并包含树节点的文件夹ID。 在ajax请求的SUCCESS配置中,有一个我想要运行的函数,它必须通过getNodeById(IdFromAjaxResponse)引用树的节点并展开它们。 问题是我不知道如何引用这些节点。 我试过this.getStore()。getNodeById但事实证明'this'指的是窗口(我猜我的容器是树面板???)。 我如何参考树面板或树存储? 我不想使用像getCmp等直接推荐。
一些代码可以帮助:
Ext.define('treePanel', {
extend: 'Ext.tree.Panel',
alias: 'widget.folderTreePanel',
//title: 'Folder Tree',
displayField: 'name',
rootVisible: false,
store: 'treeStore'
dockedItems: {
xtype: 'textfield',
name: 'Search',
allowBlank: true,
enableKeys: true,
listeners: {
specialkey: function (txtField, e) { //This handler will essentially take the search value and return the path from the DB
if (e.getKey() == e.ENTER){
var searchValue = txtField.getValue();
Ext.Ajax.request({
url: 'MyServlet',
params: {
caseType: 'search',
value: searchValue
},
success: function(response) {
response = Ext.decode(response.responseText);
var node, i=0;
expandFn = function () {
This is where I have a problem->node = this.up('treePanel').getStore().getNodeById(response.IDs[i].folderId);
node.expand();
i++;
if (i >= response.IDs.length-1) return;
expandFn();
}
}
});
}
}, scope: this
}
},
columns: [{
xtype: 'treecolumn',
text: 'Folder Name',
flex: 2,
sortable: true,
dataIndex: 'name'
},{
text: 'Folder ID',
dataIndex: 'id',
flex: 2,
sortable: true
}]
});
编辑:我找到了答案。 每个事件都将触发它的实例作为参数传递给处理函数。 在这种情况下, txtField
指的是文本字段本身。 然后我可以遍历继承并找到面板。
但是现在有一个新问题。 expandFn()
被调用ONCE然后停止,因为'node'未定义。 它应该递归,直到响应数组中没有更多项。 我认为这是一个范围问题,但我真的很困惑,我似乎没有看到出错...
listeners
配置具有属性scope
。 您可以将其设置为树面板。
[编辑]里面的specialkey监听器,分配this
一个变量。 在success
回调中,范围与特殊键的侦听器中的范围不同。 请参阅下面的修改代码。
listeners: {
scope: this,
specialkey: function (txtField, e) {
var me = this;
if (e.getKey() == e.ENTER){
var searchValue = txtField.getValue();
Ext.Ajax.request({
url: 'MyServlet',
params: {
caseType: 'search',
value: searchValue
},
success: function(response) {
response = Ext.decode(response.responseText);
var node, i=0;
expandFn = function () {
node = me.getStore().getNodeById(response.IDs[i].folderId);
node.expand();
i++;
if (i >= response.IDs.length-1) return;
expandFn();
}
}
});
}
}
问题是,你的示波器this
指的是目前的范围定义的树形面板时。 在即将定义此树面板时,无法将范围设置为树面板的实例。
要解决此问题,您可以将initComponent
函数添加到树面板并在其中设置dockedItems配置:
Ext.define('treePanel', {
extend: 'Ext.tree.Panel',
// [...]
initComponent: function() {
this.dockedItems = {
// [...]
};
this.callParent();
}
});
区别在于initComponent
是树面板的成员函数,在组件实例化期间由框架自动调用。 这时你已经有一个实例this
,你可以作为使用scope
的文本框的监听器。
它已经超过一年了,现在对extjs和javascript基础知识更加熟练。 以下是回答这个问题时应该知道的一些事情:
this
- >在javascript中总是引用调用我们使用它的函数的对象。 在我的情况下,由于函数是ajax请求的success callback
,因此无法引用treepanel
。 要解决此类问题,最好在函数顶部设置对您希望能够访问的对象的引用。 在我的情况下,我可以做var treepanel = txtField.up('treePanel');
获得对面板的引用。
expandFn
- >首先, expandFn
是在成功回调中定义的,这是另一个函数。 这会创建一个closure
,我们不希望如此。 如果我们不准备处理它,闭包提供了一些可能导致问题的特殊功能。 在treePanel
的范围内,使用expandFn
并在外部定义它。 这里最基本的问题是node = this.up('treePanel')...
this
关键字再一次没有引用我认为它的txtField
。 这就是我们之前定义treePanel
原因。 我们可以通过它访问商店。 node.expand()
需要时间来完成,特别是如果节点没有加载,我们必须发出服务器请求。 对于这种情况,执行递归的正确方法是添加一个侦听器:
node.on('expand', Ext.bind(treePanel.expandFn, treePanel, [args]), treePanel, {single:true})
有些事情需要注意:
expandFn
DIFFERENT参数传递给默认情况下由expand
事件传递的参数,我们必须使用Ext.bind
。 如果我们编写了node.on('expand', treePanel.expandFn, treePanel, {single:true})
那么当expand
事件被触发时,它将触发expandFn
但是它的默认参数根据文档是扩展节点本身和eOpts
事件选项对象。 {single: true}
以确保expandFn
仅在下一个'expand'
事件中触发。 我们不希望每次扩展节点时都触发它。 node.expand()
之前必须添加此侦听器。 这个答案不能完全应用于上面提供的代码,但它解释了它的问题以及应该如何解决它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.