如何在组件内缓存子组件实例

时间:2012-09-17 14:48:58

标签: extjs4 sencha-touch sencha-touch-2

我在网上找到很多Sencha Touch的例子,并没有真正专注于正确的视图封装。因此,即使按钮深度嵌套在视图中,Controller也会监听每个按钮的事件。换句话说,视图的内部泄漏从来都不是一件好事。

我找到了一个很好的教程,鼓励您创建有意义的观点,听取当地事件并提出有意义的商业活动等。

http://miamicoder.com/2012/how-to-create-a-sencha-touch-2-app-part-2/

然而,到目前为止我无法弄清楚的一件事是如何最好地缓存嵌套组件实例。考虑这个例子:

Ext.define("NotesApp.view.NotesListContainer", {
    extend: "Ext.Container",
    alias: "widget.noteslistcontainer",

    initialize: function () {

        this.callParent(arguments);

        var newButton = {
            xtype: "button",
            text: 'New',
            ui: 'action',
            handler: this.onNewButtonTap,
            scope: this
        };

        var topToolbar = {
            xtype: "toolbar",
            title: 'My Notes',
            docked: "top",
            items: [
                { xtype: 'spacer' },
                newButton
            ]
        };

        this.add([topToolbar]);
    },
    onNewButtonTap: function () {
        console.log("newNoteCommand");
        this.fireEvent("newNoteCommand", this);
    },
    config: {
        layout: {
            type: 'fit'
        }
    }
});

假设我们要向setSpecialUIState添加方法NotesListContainer。当它被调用时,我们想要对newButton做一些事情(例如隐藏它)。如何在不滥用newButton的情况下访问Ext.getComp()实例?我可以将其设置为实例变量吗?规范方式如何?

更新

正如Nikolaj Borisik建议的那样我试过这个。

    this._newButton = this.add([{
            xtype: "button",
            text: 'New',
            ui: 'action',
            handler: this.onNewButtonTap,
            scope: this
        }];

这就像一个魅力。我只是不知道它是否是惯用的,或者是否有任何缺点我可能会遗漏。否则我强烈建议这样做。抛开Sencha,组合有意义的视图来抽象出连贯的UI部分要好得多。这比将每个按钮泄漏到控制器并直接与它们进行操作要好得多。

所以我想知道这种方法是否有任何缺点?

3 个答案:

答案 0 :(得分:3)

除了使用getComponent()之外,我看到两个选项:

1使用Ext.create(...)作为实例组件

initialize: function () {        
   this.callParent(arguments);
   this.newButton = Ext.create('Ext.Button',{
      xtype: "button",
      text: 'New',
      ui: 'action',
      handler: this.onNewButtonTap,
      scope: this
   });
   //....
},

setSpecialUIState : function(){
   this.newButton.hide()
}

2将此逻辑移至控制器并使用refs部分

Ext.define('NotesApp.controller.Home',{
        extend : 'Ext.app.Controller',

        config : {
            refs :{
                newButton : '#noteList [itemId=newButton]'
            },

            control :{
                newButton : {
                    tap : 'onNewButtonTap'
                }
            }

        },

        onNewButtonTap : function(){
            console.log('on new Button tap');
        },

        setSpecialUIState : function(){
           this.getNewButton.hide()
        }

    });



Ext.define("NotesApp.view.NotesListContainer", {
    extend :"Ext.Container",
    alias  :"widget.noteslistcontainer",
    id     :'noteList',
    config:{
        items:[
            {
                xtype  :"toolbar",
                title  :'My Notes',
                docked :"top",
                items:[
                    { xtype:'spacer' },
                    {
                        xtype   :"button",
                        text    :'New',
                        ui      :'action',
                        itemId  :'newButton'
                    }
                ]
            }
        ]

    }
});

我更喜欢第二个选项

我使用两种选择,但在不同的情况下。我认为第一个选项更适合可以在应用程序的其他部分甚至其他项目中重用的组件。但是当我们创建一些只能使用一次的视图时,我认为不需要从视图中触发自定义事件。我们编写更多代码并复制它。是的,'newNoteCommand'比'tap'更清晰,但是{control:'#noteList [itemId ='newButton']给了我们所有必要的信息。第二个为什么我喜欢第二种选择,当我们有一个深层嵌套的组件。在这种情况下,我们应该在第一个组件中触发事件,而不是来自其父级的fire事件等,直到控制器有机会处理它。

答案 1 :(得分:1)

我认为MVVM架构更符合您的思维方式。 'VM'有一个类似控制器的组件,可以将视图与数据/动作连接起来。 KnockoutJS遵循这种范例,并将数据处理嵌入到您的视图中。

从服务器端MVC模式来看,将代码嵌入到JSP中是一个很大的禁忌。您只使用了可以执行最小逻辑的标记来呈现数据。关于以一致的方式执行此操作以大大提高代码可维护性,还有一些事情需要说明。

然而和你一样,我发现所有按钮处理程序的控制器都有点霸道。我认为你可以运用判断来确定我的行动的逻辑在哪里。如果您的行为可以重复使用,请务必使用DRY委托人。如果您使用有限的逻辑执行简单的视图特定操作 - 我可能会跳过控制器。

要了解控制器对您的观点了解太多......我同意这会导致重构问题。您可以通过让按钮处理程序从父视图中发出自定义事件来解决此问题。这样,您的控制器只需要从它已经知道的视图组件中侦听事件。缺点是您需要更多的自定义事件并将其记录得非常好,就像sencha对其事件所做的那样。否则可维护性也会受到影响。

答案 2 :(得分:1)

在我花了更多时间在Sencha之后,我发现我对Ext.getCmp()有一个错误的假设。我认为这将首先查询DOM以查找匹配的ID,然后尝试获取绑定到它的组件实例。然而,这不是它的作用。实际上,它根本不会查询DOM。它只是查询一个名为ComponentManager的工具,该工具保存对所使用的所有组件的引用。

因此,使用它不是 脏。但是,我们仍然可以做得更好。

每个容器都支持方法child(selector)down(selector)来查询子组件。乍一看,这似乎是在查询DOM,同样只查询ComponentManager。它在起始点使用容器并查询它的内部项。两者之间的区别在于child(selector)仅查询第一个子级别,而down(selector)查询所有子级别。

我想可以使用它们来处理这些子组件。但是,如果由于重复调用这些方法而仍然存在性能问题,我建议在第一次检索后缓存这些方法。