【问题标题】:Ext JS 4: Getters and setters in viewExt JS 4:视图中的获取器和设置器
【发布时间】:2013-09-23 15:41:34
【问题描述】:

我一直在思考这个问题,但我似乎无法想出一个合理的解决方案。我想做的是在我的视图中为文本字段/它的值创建 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 forums 的发帖。

编辑

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

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

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

【问题讨论】:

    标签: oop extjs extjs4 getter-setter


    【解决方案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

    【讨论】:

    • 查看更新...不确定这是否更清楚或更令人困惑,所以请告诉我。
    【解决方案2】:

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

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

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

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

    编辑

    我想我理解你所说的 getter 和 setter 是什么意思。 Ext 表单具有字段查找器,可以轻松获取和设置各个字段的数据。请参阅这些 SO 问题:Best way to access adjacent components / fieldsEXT.JS getting a list of items from a fieldset

    还像 Sergio 说的那样,表单上有 getRecord getValues 和 setRecord 方法来处理数据绑定。就是这样。

    EDIT2

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

    【讨论】:

    • Up/down/nextSibling/previousSibling/child/previousNode 似乎都如此受限制......你需要知道你与父母的关系。似乎不是很好的 OOP。请问您的声明“顺便说一句,initConfig 是设置视图的推荐方法”来自哪里? Sencha 说要这样做吗?如果是这样,您的意思是在 LoginWindow 的 initConfig 中创建我的实际按钮吗?只是好奇。另外,我对最初的问题进行了更新。
    • 查看原始问题的更新。回答您关于推荐方法的问题:config 仅在 Sencha Touch 产品中真正使用。在 extjs 中你几乎不需要它,除非你正在创建一个不扩展 extjs 组件的类。这是初始化组件的好方法:mitchellsimoens.com/?p=59
    • 有趣...从那个博客看来,我应该在 initComponent 中创建我的按钮和项目...如果我这样做了,我可以在实际类中设置对每个组件的引用,这将使我的 getter/setter 非常容易访问。
    • 我觉得那样会更贵......我想我必须先打电话给父母,然后才能推送到 LoginWindow 的 items 数组,这将迫使我调用 doLayout LoginWindow,所以它的项目/按钮会显示。明天我将对此进行试验。
    • 不,这不是它建议您做的事情。容器将其所有子组件保存在 items 数组中。您可以使用上述方法找到这些项目。不,你再也不会调用 doLayout - 这些例子你可能已经看到过时和过时了。
    【解决方案3】:

    我的想法是这样的:

    ...
    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 引用这个对象,而且我不必去寻找它当我需要它时。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多