簡體   English   中英

ExtJS 4中的范圍在函數處理程序中

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM