Javascript 四个Backbone.js模型问题

Javascript 四个Backbone.js模型问题,javascript,model-view-controller,backbone.js,Javascript,Model View Controller,Backbone.js,我使用Backbone.js跟踪可视化应用程序中的状态 该模型具有以下属性: indicatorX : "income" indicatorY : "emissions" indicatorXScale : "lin" indicatorYScale : "log" year : 1980 layout : {leftPanel : {[...]}, rightPanel : {[...]}} 1。在Backbone.js模型中,处理“依赖属性”的好方法是什么? 例如,在更改indica

我使用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"
如果模型上仅设置了指示灯,则应将比例设置为默认值:

model.set( {indicatorX : "emissions"} )
if("indicatorX" in changedAttrs){
    indicatorXScale = dataSource[indicatorX].defaultScale
}
但是,如果用户希望在“排放”指示器的情况下覆盖默认刻度,即“lin”,该怎么办

model.set( {indicatorX : "emissions", indicatorXScale : log} )
由于模型属性指示器XScale已设置为“log”,因此不会记录更改的属性。然后,我如何确保在这种情况下不加载defaultScale,而是加载传递给模型的那个

3。让模型使用额外的属性“action”来描述模型中的更改是一个好主意吗?
通过这种方式,控制器可以侦听一个属性,而不是为属性组合指定处理程序。以下是备选方案:

备选案文1。控制器具有特定属性的处理程序:

this.model.bind("change:year", this.render);
this.model.bind("change:layout", this.updateLayout);  
备选案文2。控制器具有用于模型更改和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()
}
备选案文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。在Backbone.js模型中,处理“依赖属性”的好方法是什么?例如,在更改indicatorX属性时,我还希望模型更新indicatorXScale属性

IMHO,扩展模型并绑定到变更事件中。例如:

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
这是非常基本的,但是更改事件是按键调用的,作为一个整体,“更改”。。因此,您可以绑定到某些更改中,并根据需要进行更新。如果它是一个具有大量间歇更新的关键点的大型模型,那么这绝对是一个不错的选择。如果只是那两把钥匙。。好。。您可能只需绑定一次常规ol'change事件

二,。如何处理“延迟”模型属性

重写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});
这将在模型上保持绝对“是否已设置关键点”。它可能不够具体,不能满足您的需求,但它确实有效。。因此,请随意使用和破解它

三,。让模型使用额外的属性“action”来描述模型中的更改是一个好主意吗

骨干人员设置它的方式是,正如您已经知道的,change:key专门用于某个键上的更改事件。依靠一个改变:行动,你有点像是在加上“抓住你了!”这是你的代码。我看不出其他两种方法比第一种好多少,特别是考虑到现在您已经将逻辑抛入事件侦听器中,以确定触发什么。。而不是直接将代码附加到适当的侦听器。如果有选择的话,我会坚持第一条——很明显“这个键已经更新了,所以我们要做X”。不是一个“有些东西已经更新了,让我们去弄清楚它是什么!”并且可能需要经过十几个if语句或开关

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

好吧,isEqual做了一个深刻的比较。。因此,您将面临执行所有比较代码的风险,以及递归的风险。所以,是的,如果你做了很多次,那肯定是个陷阱

引用对象当然是一个问题——我在墙上有一个很好的小洞,我已经在那里把头伸了几次,想知道为什么在一个完全不相关的地方发生了一些变化。。哦,等等。。 为了稍微纠正这一点,您可以重写get方法,在它返回对象的情况下,返回类似$.extend(true,{},this.get(key))的内容

此外,您也不知道基于普通主干的对象中到底发生了什么变化。因此,如果您正在对一个更改(重建视图等)进行大量的“工作”,那么您可能会遇到性能问题,即使您所做的只是向该对象添加另一个属性,而该属性不用于任何上述更改。(即set({layout:layoututbj})vs set({layoutPageTitle:'blah'}),它可能只更新标题..,而不会导致整个视图重新加载)

否则,至少在我正在开发的应用程序中,主干中的对象没有真正的问题。它们同步得相当好,当然比.get('layout.leftPanel[0])要好,并且有一些神奇的翻译来实现这一点。只是要小心参考部分

希望这至少有一点帮助

@Stephen:“希望这至少能帮上一点忙!”不,这很有帮助:)谢谢你给我一个非常好的回答。关于我的第三个问题,我仍然在考虑使用额外的属性“action”。。。?可以说“属性变化的特定组合”等于“一个动作”,这将是一种方便。这不是让每个控制器绑定到许多属性,也不是让每个控制器执行“高级if逻辑”,以查看哪些属性发生了更改并调用必要的函数。取而代之的是,模型只执行一次逻辑,控制器可以监听一个动作,比如scaleChange、layoutChange等。