3

这个问题我想了好久,似乎也想不出一个合理的解决方案。我想做的是在我的视图中为文本字段/它的值创建 getter/setter。我意识到首选的 Ext JS 方式是在控制器中使用引用并以这种方式获取它,但这对我来说并不是非常面向对象的。我还必须包装这些 getter 和 setter,因为如果 getter 返回未定义,我想输出一条消息。我想做的是创建自己的 getter/setter 或以某种方式覆盖默认的 getter/setter。以下是我正在考虑实现这一目标的一些方法。

我在想我可以使用config {},但这似乎只适用于我想定义的变量。然后我想以某种方式使用 id,但社区似乎对这是否是一种好习惯存在分歧。这导致了我目前的解决方案......包装。这是我的代码:

登录窗口

Ext.define('MyApp.view.LoginWindow', {
    extend: 'Ext.window.Window',
    alias: 'widget.loginWindow',
    autoShow: true,
    closable: false,
    border: 0,
    plain: true,
    allowBlank: false,
    title: "Enter your username",
    modal: true,
    config: {
        buttons: [{
            text: "Ok"
        }],
        items: [{
            xtype: 'textfield',
            fieldLabel: 'Username',
            id: 'loginUserInput',
            name: 'loginUserInput',
            msgTarget: 'under',
            validator: function(value) {
                if (Ext.isEmpty(value)) {
                    return "You need to enter a username.";
                }
                return true;
            }
        }]
    },

    constructor: function(config) {
        this.callParent(config);
    },

    getButton: function() {
        console.log('here');
    }
});

我的控制器

Ext.define('MyApp.controller.Chat', {
    extend: 'Ext.app.Controller',

    requires: [
        'Views.ChatModule.view.LoginWindow'
    ],

    refs: [{
        ref: 'loginWindow',
        selector: 'loginWindow',
        xtype: 'loginWindow',
        autoCreate: true
    }, {
        ref: 'loginUserInput',
        selector: '#loginUserInput'
    }],

    init: function() {
        // The events controller oversees
        this.control({
            'loginWindow button[text="Ok"]': {
                'click': this.onSubmitLoginWindow
            }
        });
    },

    getLoginUserInputValue: function() {
        var loginUserInput = this.getLoginUserInput();
        if (loginUserInput) {
            var username = loginUserInput.getValue();
            if (username) {
                console.log(username);
            } else {
                console.warn("username is undefined");
            }
        }
        console.warn("loginUserInput is undefined");
    },

    onSubmitLoginWindow: function(button, event, eOpts) {
        this.getLoginUserInputValue();
    }
});

这行得通,我意识到这是一件非常挑剔的事情,但是在控制器中使用 getter 感觉不对。如果它在窗口中,我觉得它会更加面向对象。但是,如果我把它放在窗口中,我相信我唯一的选择是依靠 ids 或在窗口的 initComponent 中手动创建文本字段——这将涉及保存那里对文本字段的引用,但这似乎有点低效...因为我也必须调用 doLayout 。

重申一下,我希望在 Window 中有 getter/setter,并且我正在寻找一种快速引用它的方法,类似于控制器引用对象的方式。我相信主要的答案是使用 ids 并在窗口中调用Ext.ComponentQuery.query('#loginUserInput'),但我想知道是否有更好的方法......比如覆盖自动生成的 getter/setter 或添加一个简单的 getter /setter 用于输入的值。

来自Sencha 论坛的交叉帖子。

编辑

我想我有点不清楚我想要什么。作为更一般的陈述,我不想将所有与我的视图相关的东西都塞进控制器中,而是将它们全部存储在视图本身中,其中包括诸如 getter/setter 之类的东西。其中一个 getter/setter 恰好是 loginUserInput getter。

使用模型是一个有趣的想法,但我觉得这对于单例值来说是一大笔开销。我基本上是在 LoginWindow 视图中寻找类似于 Java 的setter/getter的东西......并希望像 Java 一样简单(或接近)。

将它包含(封装)在视图中的想法使控制器更干净一些,如果我删除视图,我也会删除它的功能,所以我不必去寻找控制器中的功能。 ..我所要担心的是删除引用(应该是最少的)。

4

3 回答 3

1

我认为您正在寻找的“OO”方式是使用Ext.data.Model您的表单。如果您查看Ext.form.Basic,您有方法来操作模型(称为记录)并获取具有视图值的对象。所以你需要:

  1. 创建表单时,使用loadRecord()将表单绑定到模型。
  2. 在您需要的任何时候,使用它getValues()来检索表单字段的值。
  3. 提交表单时,使用getRecord()getValues()同步您的记录。

Ext.define('MyApp.model.Login',{
  fields : [{
    name: 'username',
    type: 'string'
  },{
    name: 'password',
    type: 'string'
  }]
});

Ext.define('MyApp.controller.Login',{
  ...
  refs : [{
    selector: 'window form',
    ref: 'formPanel'
  }],
  ...
  openForm : function() {
    //load your form and then bind the new record
    var formPanel = this.getFormPanel(), //Ext.form.Panel
        form = formPanel.getForm(); //Ext.form.Basic

    form.loadRecord(Ext.create('MyApp.model.Login'));

  },
  save : function() {
    //get the values in the view
    var form = this.getFormPanel().getForm(),
        vals = form.getValues(),
        record = form.getRecord();

    console.log(vals); //see the object representation of your view here
    record.set(vals); //update your model

    //do whatever you need with your model

  }
  ...
});

当您需要保存表单数据时,这是一个很好的示例。在登录中,我认为您可以直接使用getValues()而无需将其绑定到Ext.data.Model.

于 2013-09-23T21:44:18.860 回答
0

我的想法是这样的:

...
items: [],
constructor: function(config) {
  this.loginUserInput = Ext.create('Ext.form.field.Text', {
    fieldLabel: 'Username',
    id: 'loginUserInput',
    name: 'loginUserInput',
    msgTarget: 'under',
    validator: function(value) {
      if (Ext.isEmpty(value)) {
        return "You need to enter a username.";
      }
      return true;
    }
  });
  this.items.push(this.loginUserInput);
  this.callParent(config);
},

getLoginUserInput: function() {
  var loginUserInput = this.loginUserInput;
  if (!loginUserInput) {
    console.warn("LoginWindow::getLoginUserInput: loginUserInput is undefined");
  }
  return loginUserInput;
}

因此,我现在不是让 Ext 发挥它的魔力,而是自己实例化对象,然后我可以存储它的引用,这样我就可以在我的 getter 中轻松访问它。我只是想知道这是否会造成任何形式的性能损失。看起来并没有那么糟糕……实际上看起来会更好一些,因为我没有通过它的 ID 引用这个对象,而且我不必去寻找它当我需要它的时候。

于 2013-09-24T15:08:37.127 回答
0

老实说,我不太确定您要解决什么问题。

如果您不喜欢控制器监听窗口中的按钮,您可以让视图定义中的按钮处理程序触发控制器可以监听的自定义事件。使用fireEvent 方法。顺便说一下,initConfig 是设置视图的推荐方法。如果您愿意,您可以将其分解为方法,“this”引用可用并且是正在实例化的 View 组件。

如果您需要在 View 中查找内部组件,有许多方法可以从up/ downtonextSiblingquery.

For Components:
    • Ext.getCmp(id)
    • Ext.ComponentQuery.query()
    • up() 
    • down() 
    • nextSibling() 
    • previousSibling()
    • child()
    • previousNode()
plus various find.. Methods

编辑

我想我理解你所说的getter和setter是什么意思。Ext 表单具有字段查找器,可以轻松获取和设置各个字段的数据。请参阅这些 SO 问题:访问相邻组件/字段的最佳方法EXT.JS 从字段集中获取项目列表

也像 Sergio 所说的那样,表单上有 getRecord getValues 和 setRecord 方法来处理数据绑定。而已。

编辑2

显示清晰明了的 MVC 模式以及表单处理的最佳起点指南。http://docs.sencha.com/extjs/4.1.3/#!/guide/application_architecture

于 2013-09-23T18:13:36.900 回答