四个Backbone.js模型问题

时间:2011-09-02 09:38:40

标签: javascript model-view-controller backbone.js

我正在使用Backbone.js来跟踪可视化应用程序中的状态。

该模型具有以下属性:

indicatorX : "income"
indicatorY : "emissions"
indicatorXScale : "lin"
indicatorYScale : "log"
year : 1980
layout : {leftPanel : {[...]}, rightPanel : {[...]}}  

1。在Backbone.js模型中处理“依赖属性”的好方法是什么?
例如,在更改indicatorX属性时,我也希望模型更新indicatorXScale属性。

2。如何处理“延迟”模型属性?示例:

该模型包含:

indicatorX : "income"  
indicatorXScale : "log"

如果仅在模型上设置了indicatorX,则应将比例设置为默认值:

model.set( {indicatorX : "emissions"} )
if("indicatorX" in changedAttrs){
    indicatorXScale = dataSource[indicatorX].defaultScale
}

如果用户想要覆盖“排放”指示符中“lin”的默认比例,该怎么办?

model.set( {indicatorX : "emissions", indicatorXScale : log} )

由于模型属性indicatorXScale已设置为“log”,因此不会记录更改的属性。那么如何确保在这种情况下不加载defaultScale - 而是传递给模型的那个?

第3。让模型使用额外的属性“动作”来描述模型中的变化是不是一个好主意?
通过这种方式,控制器可以侦听一个属性,而不是为属性组合指定处理程序。这些是替代方案:

Alt 1. Controller具有特定属性的处理程序:

this.model.bind("change:year", this.render);
this.model.bind("change:layout", this.updateLayout);  

Alt 2. Controller具有模型更改处理程序,render()指出要执行的操作:

this.model.bind("change", this.render);
render() {
   var changedAttributes = this.model.changedAttributes
   if (a,b && c in changedAttributes) x()
   if (a,d in changedAttributes) y()
}

Alt 3.让模型描述属性变化的组合意味着什么:

this.model.bind("change:action", this.render);
render() {
   var changedAttributes = this.model.changedAttributes
   var action = this.model.get("action")
   if (action == gui_changeIndicator) x()
   if (action == gui_opacity) y()
}

4。在Backbone.js模型中使用对象作为属性时,是否有任何缺陷需要注意?
例如,在我试图保留在我的模型中的布局状态上执行isEqual是否昂贵?此外,在设置模型时,对象是通过引用传递的,因此最好是比较的新对象吗?

1 个答案:

答案 0 :(得分:10)

1。在Backbone.js模型中处理“依赖属性”的好方法是什么?例如,在更改indicatorX属性时,我也希望模型更新indicatorXScale属性。

恕我直言,扩展模型并绑定到更改事件。例如:

MyModel = Backbone.Model.extend({
    initialize: function() {
        this.bind('change:width', this.updateArea);
        this.bind('change:height', this.updateArea);
        this.updateArea();
    },
    updateArea: function () {
        this.area =  this.get('width') * this.get('height');
    }
});

var model = new MyModel({height: 10, width: 10});
console.log(model.area); //100
model.set({width: 15});
console.log(model.area); //150

这是非常基本的,但更改事件是按键调用的,并且整体上是“更改”..因此您可以绑定到某些更改并根据需要进行更新。如果它是一个大型模型,其中许多键间歇性地更新,这绝对是可行的方法。如果它只是那两个键..好吧..你可能只能绑定常规的'变更事件一次。

2。如何处理“延迟”模型属性?

覆盖set方法并添加一些自己的代码。例如:

MyModel = Backbone.Model.extend({
    constructor: function (obj) {
        this.touched = {}; //Set before the prototype constructor for anything being set
        Backbone.Model.prototype.constructor.call(this, obj);
        //set after for only things that the program has updated.
        return this;
    },
    set: function(attributes, options) {
        if(attributes.keyIWantToListenFor !== undefined && !this.touched.keyIWantToListenFor) {
            console.log("keyIWantToListenFor was set, let's fire off the right methods");
            this.touched.keyIWantToListenFor = true;
        }
        Backbone.Model.prototype.set.call(this, attributes, options);
        return this;
    }
});

var model = new MyModel({height: 10, width: 10});
model.set({keyIWantToListenFor: 15});

在模型上保持绝对“已经设置了密钥”。它可能不是特定于你的需求,但它确实有效..所以随意使用并劈开它。

3。让模型使用额外的属性“action”来描述模型中的变化是一个好主意吗?

Backbone人员设置它的方式是,正如您所知,更改:key专门针对某个键上的更改事件。依靠变化:行动,你可以在你的代码中加入'gotcha!'。我没有看到其他两个方法如何比第一个方法更好,特别是考虑到现在你已经将逻辑抛入事件监听器以确定要触发的内容......而不是直接将该代码附加到适当的侦听器。如果有选择,我会坚持使用第一个 - 这是明确的“这个键已经更新,所以我们要做X”。不是“事情已经更新,所以让我们弄清楚它是什么!”并且可能必须通过十几个if语句或开关。

4。在Backbone.js模型中使用对象作为属性时,是否有任何陷阱需要注意?

嗯,isEqual执行深度比较..所以你冒着做所有比较代码的风险加上递归的风险。所以,是的,如果你多次这样做,那肯定是一个陷阱。

参考对象肯定是一个问题 - 我在墙上有一个漂亮的小洞,我已经几次想知道为什么在一个完全不相关的东西中发生了变化哦等等.. 为了解决这个问题,你可以覆盖get方法,在它返回一个对象的情况下,返回类似$ .extend(true,{},this.get(key));

另外,你真的不知道基于普通Backbone在对象中究竟发生了什么变化。所以,如果你在更改(重建视图等)上做了很多'东西',你可能会遇到性能问题,即使你所做的只是为该对象添加另一个属性而它不是用于任何所述更改。 (即set({layout:layoutObj})vs set({layoutPageTitle:'blah'}),它们只能更新标题..而不是导致整个视图重新加载。)

否则,至少在我正在开发的应用程序中,我们对主干中的对象没有任何实际问题。它们同步得很好,它肯定比.get('layout.leftPanel [0]')更好,并且有一些神奇的翻译来使它工作。请注意参考部分。

希望至少有一点帮助!