ExtJS 4中的范围在函数处理程序中

时间:2014-05-22 11:10:31

标签: javascript extjs scope extjs4 handler

我已经对范围问题进行了一些搜索,发现了一些问题,但我不确定它们是否符合我的情况。我真的很困惑,所以我想我也可以直接问论坛。

我有一个树形图。在该树面板中,我有一个xtype的dockedItem:' textfield'。该textfield接受一个值,并通过在特殊键事件的处理程序内的Ext.Ajax.Request将其用作ajax请求中的参数。服务器在其响应上返回一个JSON对象,该对象将被解码并包含树节点的文件夹ID。在ajax请求的SUCCESS配置中,有一个我想要运行的函数,它必须通过getNodeById(IdFromAjaxResponse)引用树的节点并展开它们。问题是我不知道如何引用这些节点。我试过这个.getStore()。getNodeById但事实证明这个'这个'指的是窗口(我猜我的容器是树面板???)。我如何参考树面板或树存储?我不想使用像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然后停止,因为'节点'未定义。它应该递归,直到响应数组中没有更多项。我再次认为这是一个范围问题,但我真的很困惑,我似乎没有看到出错...

3 个答案:

答案 0 :(得分:2)

listeners配置有一个属性scope。您可以将其设置为树面板。

[编辑]在特殊键侦听器中,将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();
                        }
                    }
                });
            }
}

答案 1 :(得分:0)

问题是,您的范围this是指定义树面板时的当前范围。当即将定义此树面板时,您无法将范围设置为树面板的实例。

要解决此问题,您可以在树面板中添加initComponent函数并在其中设置dockedItems配置:

Ext.define('treePanel', {
    extend: 'Ext.tree.Panel',

    // [...]

    initComponent: function() {
        this.dockedItems = {
            // [...]
        };

        this.callParent();
    }
});

不同之处在于initComponent是树面板的成员函数,在组件实例化期间由框架自动调用。目前,您已经有一个实例this,您可以将其用作文本字段听众的scope

答案 2 :(得分:0)

它已经超过一年了,现在对extjs和javascript基础知识更加熟练。以下是回答这个问题时应该知道的一些事情:

success callback - >在javascript中始终引用调用我们使用它的函数的对象。在我的情况下,由于函数是ajax请求的treepanel,因此无法引用var treepanel = txtField.up('treePanel');。要解决此类问题,最好在函数顶部设置对您希望能够访问的对象的引用。在我的情况下,我可以expandFn来获取对该面板的引用。

expandFn - >首先,closure在成功回调中定义,这是另一个函数。这会创建一个expandFn,我们不希望这样。如果我们不准备处理它,闭包提供了一些可能导致问题的特殊功能。取treePanel并在node = this.up('treePanel')...的范围内定义它。这里最基本的问题是this txtField关键字再次没有引用我认为它的treePanel。这就是我们之前定义node.expand()的原因。我们可以通过它访问商店。另外node.on('expand', Ext.bind(treePanel.expandFn, treePanel, [args]), treePanel, {single:true})需要时间来完成,特别是如果节点未加载并且我们必须发出服务器请求。对于这种情况,正确的递归方法是添加一个监听器:

Ext.bind

有些事情需要注意:

  • 如果我们想要将{DALFERENT参数传递给expandFn而不是默认传递给expand事件的参数,我们必须使用node.on('expand', treePanel.expandFn, treePanel, {single:true})。如果我们写了expand那么当expandFn事件被触发时它将触发eOpts但是它的默认参数根据文档是扩展节点本身和{single: true}事件选项对象。
  • 我们添加expandFn以确保仅在下一个'expand'事件中触发node.expand()。我们不希望每次扩展节点时都触发它。
  • 必须先添加此侦听器,然后才能使用onclick

这个答案不能完全应用于上面提供的代码,但它解释了它的问题以及应该怎样做才能解决它。