【问题标题】:backbone.js models pointing to same instance of nested model指向嵌套模型的相同实例的主干.js 模型
【发布时间】:2011-09-15 18:34:59
【问题描述】:

使用backbone.js,这里有一个快速测试来演示我在使用嵌套模型时遇到的问题。

前言 我有一个包含 2 个嵌套模型 Obj1 和 Obj2 的 Obj 模型。 Obj模型本身有一个View(ObjView),主页面本身也有一个View(BodyView)。

主页有一个按钮,id=add。每次单击按钮时,ObjCollection 中都会添加一个新的 Obj,ObjView 会在页面中添加一个按钮(id=clickMe)。 clickMe 按钮绑定到控制台记录 this.model 和 this.model.get("obj1") 的 testFunc。

问题 通过检查 console.logs,我看到虽然每个 Obj 都是一个新实例,但它们嵌套的 Obj1 指向同一个 obj1 实例!但是 Obj 的每个实例显然应该有自己的嵌套模型 obj1 和 obj2 的实例。

任何帮助表示赞赏。

$(document).ready(function(){

    var Obj1 = Backbone.Model.extend({
        defaults:{
            Attr1A   : false,
            Attr1B   : false
        }
    })

    var Obj2 = Backbone.Model.extend({
        defaults:{
            Attr2A   : false,
            Attr2B   : false
        }
    })

    var Obj = Backbone.Model.extend({
        defaults: {
            obj1    : new Obj1(),
            obj2    : new Obj2()
        }
    })

    var ObjCollection = Backbone.Collection.extend({
        model: Obj
    });


    var ObjView = Backbone.View.extend({

        initialize: function(){
            _.bindAll(this, 'render', 'testFunc');
            this.model.bind('change', this.render);
            this.model.view = this;

            $("body").append(this.render().el);
        },

        events: {
            "click #clickMe" : "testFunc"
        },

        render: function(){
            $(this.el).html('<input type ="button" id="clickMe" value="Click">')
            return this;
        },

        testFunc: function(){
            console.log(this.model); //returns Obj models with unique cids
            console.log(this.model.get("obj1")); //returns Obj1 models with the SAME cid!
        }
    });


    var BodyView = Backbone.View.extend({
        el: $('body'),

        events:{
            "click #add"  : "addObj"
        },

        initialize: function(){
            _.bindAll(this, 'render', 'addObj')
            this.collection = new ObjCollection();
            this.collection.bind('add', this.appendObj); 
        },

        addObj: function(){
            var myObj = new Obj();
            this.collection.add(myObj);
        },

        appendObj: function(myObj){
            var objView = new ObjView({
                model: myObj
            });
        }
    });
    var bodyView = new BodyView;

});

html 页面就是以下加载了 jQuery 和主干的页面。

<body>
    <input type ="button" id="add" value="Add">
</body>

【问题讨论】:

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


    【解决方案1】:

    与:

    var Obj = Backbone.Model.extend({
        defaults: {
            obj1    : new Obj1(),
            obj2    : new Obj2()
        }
    })
    

    您是说您希望使用“Obj”创建的所有对象都具有相同的“obj1”和“obj2”值,请使用:

    var Obj = Backbone.Model.extend({
        initialize: function() {
            this.obj1 = new Obj1();
            this.obj2 = new Obj2();
        }
    });
    

    实现你所看到的想要的。 http://documentcloud.github.com/backbone/#Model-constructor

    【讨论】:

    • 感谢您的帮助,但我不确定为什么 this.model.get("obj1") 现在给了我 undefined?我认为它会默认返回 Obj1 的一个实例。有什么想法吗?
    • @fortuneRice 试试this.get("obj1"),obj1 不是“类”Obj 的属性,而是Obj 实例的属性。
    • 感谢您的跟进;我根据关于内部属性数组的解释接受了 c3rin 的解决方案。
    【解决方案2】:

    fortuneRice,当一个 Backbone 模型被初始化时,super.constructor 将默认值移动到内部属性数组,其中 model.get 查找“obj1”。 Prusse 的示例使用每个实例的新对象初始化 obj1 和 obj2 值,但不会将值移动到内部属性数组。这是我对 Prusse 解决方案的修改。

    var Obj = Backbone.Model.extend({
        initialize: function() {
            myDefaults = {
                obj1: new Obj1();
                obj2: new Obj2();
            }
            this.set(myDefaults);
    });
    

    jQuery 的 extend 方法将结合这两个对象。您可以在 initialize 方法中使用默认值声明非对象引用和使用 myDefaults 声明对象引用。

    【讨论】:

    • 为什么不使用this.set(myDefaults) 而不是$().extend(...)?在内部它做同样的事情,并且会产生同样的效果,但我相信使用 set 更干净。
    • @idbentley 哦,我想你可以做到!甚至没有想到它,但是,是的,它会更干净。您可以使用 set 触发更改事件,但您可以使用静默选项,所以我想这并不重要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 2012-03-29
    • 2014-12-21
    • 1970-01-01
    相关资源
    最近更新 更多