Backbone.js - 正确的模型初始化
Posted
技术标签:
【中文标题】Backbone.js - 正确的模型初始化【英文标题】:Backbone.js - proper model initialization 【发布时间】:2012-08-30 10:49:28 【问题描述】:问题:当存在需要以特定方式存储的属性时,初始化backbone.js 模型的正确方法是什么?我是否需要映射不需要任何特殊格式的属性?我认为backbone.js 做了某种自动映射。
示例:
var MyModel = Backbone.Model.extend(
initialize: function (options)
// These attributes need to be stored in a different format
// Dates
this.startYear = new Date(options.startTime).getFullYear();
// Rounding numbers
this.wholeNumber = Math.Round(options.numberWithDecimals);
// Storing empty strings as nulls
if (options.fullName == null || options.fullName == "")
this.fullName == null;
else
this.fullName = options.fullName;
// These are fine as they are
this.fieldA = options.fieldA;
this.fieldB = options.fieldB;
this.fieldC = options.fieldC;
,
);
【问题讨论】:
你在考虑parse
吗?
身份证。我是吗?有没有更好/更容易/更合适的方法来做我在这个例子中所做的事情?
parse
在您通过fetch
获取属性时被调用。也就是说你shouldn't 需要手动指定不需要修改的属性,对于那些你可能应该使用set(例如this.set(startYear:= new Date(options.startTime).getFullYear())
)。
@Jack: parse
如果你指定了parse:true
选项,也会被构造函数调用,但这并没有记录在案。
@muistooshort 我不知道,谢谢。
【参考方案1】:
首先您必须区分attributes
和instance variables
。
属性:恕我直言,它应该是字符串或整数形式的普通对象。它们通过 REST API 在客户端和服务器之间移动。它们通过Model.get()/Model.set() 方法进行操作。它们通过Model.toJSON() 发送到服务器(也使用相同的.toJSON()
方法将它们发送到template
。如果它们以某种方式发生变化,则触发主干事件。您可以自定义此 attributes
的初始化,在将其发送到覆盖 @muistooshort 建议的 Model.parse() 方法的模型之前操作服务器端 JSON 信息。
实例变量:(this.myAttribute
事物)它们可以是复杂的对象。它们的更改不会触发任何隐式事件,它们不会在 save
和 update
调用中发送到服务器,并且以标准方式,它们不会发送到 模板.
在您的示例中,您没有存储任何复杂的对象,并且如果您不担心您的模型会向服务器发送比从服务器接收的属性更多的属性,您可以寻求@muistooshort 建议:
// code no tested
var MyModel = Backbone.Model.extend(
parse: function(resp, xhr)
resp.startYear = new Date( resp.startTime ).getFullYear();
resp.wholeNumber = Math.Round( resp.numberWithDecimals );
if( resp.fullName == "" ) resp.fullName == null;
return resp;
,
);
记住这些是属性,你必须以这种方式访问它们my_model.get( "startYear" )
此解决方案的唯一问题是,如果 原始属性 更改,派生属性 将不会更新。所以你可以用另一个实现:
// code no tested
var MyModel = Backbone.Model.extend(
initialize: function()
this.updateAttributes();
this.on( "change", this.updateAttributes, this );
,
updateAttributes: function()
this.set( "startYear", new Date( this.get( "startTime" ) ).getFullYear() );
this.set( "wholeNumber", Math.Round( this.get( "numberWithDecimals" ) ) );
if( this.get( "fullName" ) == "" ) this.set( "fullName", null );
,
);
更新
正如@TomTu 所建议的,如果您的 onlive 属性 只需要提供模板,那么 decorator 是最好的解决方案:https://***.com/a/9687672/316700
【讨论】:
AFAIK 你必须说new M(..., parse: true)
让构造函数使用parse
,这似乎没有记录在任何地方。
@muistooshort 我认为不需要github.com/documentcloud/backbone/blob/master/backbone.js#L339
但如果你只是在没有fetch
的情况下使用new M(...)
:github.com/documentcloud/backbone/blob/master/backbone.js#L187
@muistooshort 非常正确!我不知道,我希望到时候我会记得它,否则它会让我大吃一惊。
如果你每次保存时都这样做,你会向服务器发送你以这种方式引入的所有更改和额外属性的开销 - 这是一种非常糟糕的方法 IMO【参考方案2】:
如果您只需要在模板中使用辅助值,您可以在覆盖的 toJSON
方法中计算它们,该方法将添加在视图中表示模型时可能需要的所有额外属性。
As the documentation for Backbone.js says:
model.toJSON()
返回模型属性的副本以进行 JSON 字符串化。 这可用于持久化、序列化或增强 在被移交给视图之前。 ...
正如我在另一个答案的评论中提到的那样 - 在 parse
方法中更改模型将导致创建开销,每次保存模型时都会将其发送到服务器,应该被认为是一种草率和不好的做法
由于模型初始化不会以与视图类似的方式将选项绑定到模型实例,因此您始终可以在初始化方法中执行此操作,然后根据需要引用覆盖的 toJSON 方法中的选项随心所欲地实现
【讨论】:
我不确定,但我认为如果您操纵.toJSON()
,该操纵将对服务器通信产生影响,因此您遇到的问题与我的方法相同。
我想这就是它发生的地方:github.com/documentcloud/backbone/blob/master/backbone.js#L1359
曾担心我在那里看到过 - 似乎序列化模型上的 attributes 属性应该是一个更好的主意。似乎提供某种 toJSON 的替代方案是唯一有意义的事情,而无需更改核心并且不必在每次发生更改时都更新模型上的自定义属性。实际上,现在我记得我曾经为此目的创建了一个名为 toTemplateData() 的方法,因为我们需要传递一些更大的嵌套数据对象,这会导致大量开销。可能值得在 github 上提出一个关于它的问题。
没错,在 onlive 属性 只需要提供模板的前提下,decorator 是最好的解决方案:***.com/a/9687672/316700 (但是问题中没有提到这个前提,这是因为我想出了更具侵入性的方法)..更新我的答案【参考方案3】:
已经回答了,只是为了更整洁一点:
var contact = Backbone.Model.extend(
parse: function (response)
response.newAttribute = response.alreadyProvidedAttribute;
return response;
);
【讨论】:
以上是关于Backbone.js - 正确的模型初始化的主要内容,如果未能解决你的问题,请参考以下文章
比较Backbone.js, Angular.js, Ember.js, Knockout.js