【问题标题】:Backbone.js add a computed attribute to model after it's parsedBackbone.js 在解析后向模型添加计算属性
【发布时间】:2013-12-04 13:10:50
【问题描述】:

在 Backbone 中,有一种方法可以在同一个模型被解析后在模型上执行一个函数。

我有带有基础数据的模型,并且想要计算组合基础数据的另一个属性。

目前我在模型内部设置了一个函数来创建和添加属性,这是在通过循环遍历每个模型从服务器获取数据后执行的,但这并不理想。

var Report = Backbone.Model.extend({

    generateURL: function(){
        var sURL = '', sHash = '';

        sHash += this.get('reportid');
        sHash += 'p1' + app.venue.info.get('loginid');

        sURL += 'r=' + this.get('reportid');
        sURL += '&p1=' + app.venue.info.get('loginid');

        _.each(this.params, function(param){
            sURL    += '&' + param.name + '=' + param.value;
            sHash   += param.name + param.value;
        });

        sURL += '&h=' + new jsSHA((sHash + this.collection.sKey),'TEXT').getHash('SHA-1','HEX');

        this.set({"url":sURL});

    }

});

var Reports = Backbone.Collection.extend({

    model: Report,
    sKey: '***********',
    url: function(){
        return '/reports/venue/'+ app.venue.info.id;
    },

});

app.venue.reports.set([{id:0,reportid:3,params:null,report_name:'Report3'},{id:1,reportid:2,params:null,report_name:'Report2'}]);

app.venue.reports.each(function(report){ report.generateURL(); });

【问题讨论】:

    标签: javascript backbone.js


    【解决方案1】:

    您当然可以覆盖.parse() 函数并为所欲为。

    var Mod = Backbone.Model.extend({
        parse: function(response){
            response.new_attr = response.old_attr + 1;
            return response;
        }
    })
    

    【讨论】:

    • 是的,但我想将 attr 存储在模型上,如 id 并且也让它们有效。还考虑使用 hasChanged 重新计算 url。
    • 另一个问题是当你使用 Collection.set() 时,模型解析永远不会被调用。
    【解决方案2】:

    Dazzer13,Stephen 的做法是正确的(这是 parse 函数的主要用途之一)。

    首先要考虑的是, parse() 返回的任何内容都将用作模型的基础数据。因此,假设您的回复包含:

    { 
      id: 1556,
      first_name: "John"
      last_name: "Doe"
    }
    

    您可以使用 parse 来修改此哈希并添加新的计算值,例如

    parse: function(response) {
      response.initials = response.first_name[0]+response.last_name[0];
      return response;
    }
    

    这与使用以下哈希创建模型完全一样:

    { 
      id: 1556,
      first_name: "John"
      last_name: "Doe"
      initials: "JD"
    }
    

    这意味着在那之后,您可以执行 model.get("initials") 并且它将包含您的计算值。如果您执行 model.save(),它会将数据中的首字母发送到服务器:实际上,Backbone 内部总是在服务器的响应上调用解析,但默认解析只是执行“返回响应;”。这就是为什么这些新属性将与普通属性完全一样,因为它们与其他属性经历相同的机制。

    对于您的第二个问题,确实调用 Collection.set()(或 add)不会调用 parse... 除非您给它选项 {parse: true}!其原因是 set() 应该(至少基于文档)用于设置具有骨干模型的集合,而不是用于 javascript 原始对象。它将 javascript 原始对象动态转换为骨干模型这一事实比其他任何东西都更方便。

    【讨论】:

      【解决方案3】:

      试试 Alex Beletski 的 backbone-computedfields。 它非常广泛和健壮,可以处理事件、更改、依赖项、JSON 和验证。项目页面中的一个简单示例:

      var Model = Backbone.Model.extend({
          defaults: {
              'netPrice': 0.0,
              'vatRate': 0.0
          },
      
          initialize: function () {
              this.computedFields = new Backbone.ComputedFields(this);
          },
      
          computed: {
              grossPrice: {
                  depends: ['netPrice', 'vatRate'],
                  get: function (fields) {
                      return fields.netPrice * (1 + fields.vatRate / 100);
                  }
              }
          }
      });
      
      model = new Model({ netPrice: 100, vatRate: 20});
      model.get('grossPrice')     // -> 120 is returned
      

      【讨论】:

        猜你喜欢
        • 2013-04-14
        • 2018-07-30
        • 2019-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-22
        • 2016-06-19
        相关资源
        最近更新 更多