6

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

我找到了一个很好的教程,它鼓励您创建有意义的视图来聆听本地事件并引发有意义的业务事件等。

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 部分要好得多。这比将每个按钮都泄漏到控制器并直接摆弄它们要好得多。

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

4

3 回答 3

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'] 给了我们所有必要的信息。第二为什么我更喜欢第二种选择,当我们有深层嵌套的组件时。在这种情况下,我们应该在第一个组件中触发事件,而不是从他的父级触发事件等等,直到控制器有机会处理它。

于 2012-09-17T18:50:00.630 回答
1

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

所以,使用它并没有那么脏。但是,我们仍然可以做得更好。

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

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

于 2012-10-08T11:56:31.150 回答
1

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

来自服务器端 MVC 模式,将代码嵌入 JSP 是一个很大的禁忌。您只使用了可以执行最少逻辑来呈现数据的标签。关于以一致的方式执行此操作以大大提高代码的可维护性,有一些话要说。

但是,像您一样,我发现为所有按钮处理程序引用控制器有点霸道。我认为你可以判断我的行动逻辑在哪里。如果您的操作可重用,请务必使用 DRY 主体。如果您正在执行具有有限逻辑的简单视图特定操作 - 我可能会跳过控制器。

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

于 2012-09-19T17:22:07.250 回答