覆盖 ExtJS 模型的 getter 和 setter 的最佳实践

4
我希望能够拦截模型上的字段获取/设置,以便在它们显示之前和存储到模型之前转换值。在这种情况下,我想在模型中存储URI编码数据,但是显示解码后的值。
当我直接覆盖get/set方法时,我发现代理正在使用它们将原始数据放入模型中。我不想覆盖该过程,也不确定如何判断是代理加载模型还是UI。
什么是最佳方法?顺便说一句,convert似乎是一个糟糕的选择。它不是双向且实时的。

1
convert() 是一个双向方法。例如,我使用它来在十进制颜色代码和十六进制之间进行转换。 - sha
只是为了我理解... (1) 在检索数据时,您在ajax获取之前对服务器上的数据进行编码,然后在显示数据给最终用户之前进行解码?(2) 当在URL中传递数据时,您会对其进行编码,然后在使用数据时在Ext JS中进行解码?(3) 在保存数据时,您会让Ext JS进行编码,然后将其传递给服务器并在存储之前进行解码? - Entree
如何转换一个双向函数?在我看来,它似乎只有在读取记录的值时才会被调用,例如 myRec.get('field1')。是否存在一个转换等效项在写操作期间被调用,例如 myRec.set('field1', 'new value')? - Paul
1个回答

4
注意:我没有测试这段代码,如果您有问题,请使用这些概念并稍后评论。
当您为数据实体定义Ext.data.Model类时(对于Ext JS 3,请使用Ext.data.Record),请将转换函数作为Ext.data.Field属性实例的一部分添加。如果您想要为所有字段执行此操作,但可能不建议这样做。
我对这个框架还很陌生,所以我不知道如何在转换函数中使用“this.self”符号,以防您在Model类中扩展另一个类。例如,如果您在Employee类中没有定义默认值,并且它继承自另一个类(例如Employee),但Employee构造函数设置了该属性,则在编码数据时,它将采用在超类(基类或父类)构造函数中定义的值。现在,它只获取EmployeeDeveloper.dataValue属性。
Ext.define('EmployeeDeveloper', {
  extend: 'Ext.data.Model',
  fields: [
    { name: 'name', type: 'string', defaultValue: 'Paul' },
    { name: 'profession', type: 'string', defaultValue: 'Ext JS developer' },
    { name: 'salary', type: 'float', defaultValue: '95000' },
    { name: 'dataValue', type: 'string',
      convert: function(value, record) {
        // feel free to use value and record parameters in this function
        return encodeData(record.get('dataValue'));  // you may have to use the "value" parameter instead of record.get('dataValue') if referencing the field in it's own convert function (haven't tested)
      }
    }
  ]
});

var empDev = Ext.create(
  'EmployeeDeveloper', 
  {
    name: 'MacGyver',
    dataValue: 'ABC'
  }, 
  'MacGyver', 
  123
);

var encodedDataValue = empDev.get('dataValue');

关于convert的注意事项: 如果您引用的字段在convert函数签名下方定义,代码将不知道它并且无法检索该值。

或者如果您有一个自定义类但不使用模型类...

今晚我也读到了一些关于Ext JS中很有趣的东西。他们在Ext JS 4中添加了自动getter和setter。框架的新版本会自动在您定义的类的“config”属性内部以“get”、“set”、“reset”或“apply”为前缀,并将属性的第一个字母大写。

在常规JavaScript中,他们没有真正的类,但是Sencha已经使定义类(使用“define”函数)和实例化用户定义类的对象实例成为可能。

例如,假设您定义了以下类:

Ext.define('Paul.MyClass'), {
  extend: 'Ext.Window',
  config: {
    name: 'Paul'
  }
});

如果您像这样创建对象实例,您将自动获得四个函数的访问权限。
var win = Ext.create('Paul.MyClass');  // create instance of MyClass object
var myName = win.getName();  // get name
win.setName('MacGyver');  // set name
win.resetName(); // this resets the value back to the default value ('Paul')
win.applyName();  // this calls custom code 
win.show();

我建议使用你提出的逻辑来覆盖apply*方法。然后在获取新值之前调用win.get*();。最好为每个要编码的字段添加一个额外的编码字段,这样每次在代理和/或存储中访问(获取或设置)数据时就不必操作属性了。
Ext.define('Paul.MyClass'), {
  extend: 'Ext.Window',
  config: {
    name: 'Paul',
    dataValue: 'non encoded value of your data'
  }
  applyName: function(title) {
    this.name = this.name + ' ' + title;  // custom logic goes here
  }
  applyDataValue: function(encodeKey) {
    // get the encoded data value
    this.self.dataValue = 'encoded data value';  // custom logic goes here
  }
});

我正在使用ExtJS 4.1和Sencha Touch 2.0 - 所以两者都有自动getter和setter。关于转换,我仍然不确定它如何帮助写入,它似乎只在转换读取方面有用。也许我可以重写getter和setter,但在我的看来,即使在加载时(例如model.add(newRec)操作),getter和setter也会被调用,这对我来说不好。 - Paul
我还没有用过Ext JS编程,只是在这个周末制作了一些小部件,并阅读了一本相关的书籍。我刚刚得到了一份工作(入门级),将使用这个框架为当地的诊所开发数据仓库报告工具,所以我会快速学习。如果我在这本书中或在网上阅读到一些信息,我会回复你的。你可能想在sencha.com论坛上发布一个带有这些信息的问题。 - Entree
model.add(newRec) 没有做什么? - Entree
我的问题涉及到model.add(newRec)在做什么。它正在调用属性的getter和setter。我只希望当UI访问模型时才调用我的getter和setter,而不是代理加载模型时。 - Paul
你能在描述的场景下尝试调用getters和setters中的showCallStack函数,看看有什么不同或者哪些变量不同吗?该函数将警报调用堆栈。然后你可以回溯,这样就可以对你的getters/setters进行某种方式的hack,使其在需要时返回到开头(或被忽略),并返回字段/属性的当前值而不是编码值。http://www.webdeveloper.com/forum/showthread.php?t=141861 - Entree

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接