![](/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.