Sharing a model between views in backbone.js

I am working on a phonegap app using backbone.js. I have the following models:

  • A Measure
  • A Measures Collection (basis of the main view)
  • A Code
  • A Codes collection (child of Measure)
  • I then have the following Views

  • Main Page
  • List of Measures
  • Measure page
  • Code List Page (codedOptionsPage) (includes a header and then a div that is the container for the list)
  • Code List collection view (codedItemListView, manages the list in the above page)
  • Code Item (codedItemView - one for each list item)
  • I want the Measure object to be the model for all Views 3 - 6 so that, when anything changes, I can update the main object and save it.

    What is happening in the code below is that, upon first render for the codedOptionsPage, the "this.model" is an instance of the Measure model. However, on subsequent calls to render triggered by adding a code to the Measure's code collection, "this.model" is a reference to the prototype, not an instance, so I get an error saying "Object function (){ return parent.apply(this, arguments); } has no method 'toJSON'"

    I am pretty sure the code below is not what it should be, as I'm still struggling through this approach, and I'm happy to take general advice, but I'm particularly wondering what is happening to the model.

    directory.views.codedOptionsPage = Backbone.View.extend({
        events : {
            "click a.add-item" :"add"
        },
        initialize: function () {
            this.template = _.template(directory.utils.templateLoader.get('coded-options-page'));
            this.model.attributes.codes.bind('add', this.render);
            _.bindAll(this, "add");
        },
        add: function() {
            var code = new directory.models.code();
            this.model.attributes.codes.add(code);
        },
        render: function(eventName) {
            $(this.el).html(this.template(this.model.toJSON()));
            this.listView = new directory.views.codedItemListView({el: $('ul.codes', this.el), model: this.model});
            this.listView.render();
            return this;
        }
    });
    
    directory.views.codedItemListView = Backbone.View.extend({
        el: 'ul.code-list',
        initialize: function() {
            this.model.bind("reset", this.render, this);
        },
        render: function(eventName) {
            $(this.el).empty();
            _.each(this.model.attributes.codes, function(code) {
                var li = new directory.views.codedItemView({model: code}).render().el;
                $("#code-list").append(li);
            }, this);
            return this;
        }
    });
    
    directory.views.codedItemView = Backbone.View.extend({
        tagName: "li",
    
        initialize: function() {
            this.template = _.template(directory.utils.templateLoader.get('coded-item'));
        },
    
        render: function(eventName) {
            $(this.el).html(this.template(this.model.toJSON()));
            return this;
        }
    });
    

    Thanks for looking!


    这可能不是解决您的问题的方法,但肯定会有一些更改,我会建议您使代码更清晰。

    directory.views.codedOptionsPage = Backbone.View.extend({
        events: {
            "click a.add-item": "add"
        },
        initialize: function () {
            this.template = _.template(directory.utils.templateLoader.get('coded-options-page'));
            // You seem to render the Whole List View when you add a new Code Model
            // to the collection .. I think it should be moved to the child View which render the 
            // code Model
            //this.model.attributes.codes.bind('add', this.render);
            // Use .get('name') to access the attributes
            // Save it to a Variable so that you can pass this in
            this.codesCollection = this.model.get('codes');
            _.bindAll(this, "add");
        },
        add: function () {
            var code = new directory.models.code();
            this.codesCollection.add(code);
        },
        // Create a new method and move the rendering of listView here
        // as it seperated the functionality of the methods
        renderListView: function () {
            var listView = new directory.views.codedItemListView({
                el: $('ul.codes', this.el),
                model: this.model,
                // Pass in the collection
                collection: this.codesCollection
            });
            listView.render();
        },
        render: function (eventName) {
            $(this.el).html(this.template(this.model.toJSON()));
            this.renderListView();
            return this;
        }
    });
    
    directory.views.codedItemListView = Backbone.View.extend({
        el: 'ul.code-list',
        initialize: function () {
            // Moved the Add event on collection to this view
            // Use listenTo to attach events instead of bind and on
            this.listenTo(this.collection, 'add', this.renderCodedItem);
            // Replacing this with listen
            //this.model.bind("reset", this.render, this);
            this.listenTo(this.model, 'reset', this.render);
        },
        // Moved the rendering of the ItemView to a different method
        renderCodedItem: function (code) {
            var li = new directory.views.codedItemView({
                model: code
            });
            // Appending the el of the ItemView to code-list
            $("#code-list").append(li.el);
            // Render the item
            li.render();
        },
        render: function (eventName) {
            // Use this.$el to access the el element
            //$(this.el).empty();
            this.$el.empty();
            _.each(this.collection, function (code) {
                this.renderCodedItem(code);
            }, this);
            return this;
        }
    });
    
    directory.views.codedItemView = Backbone.View.extend({
        tagName: "li",
        initialize: function () {
            this.template = _.template(directory.utils.templateLoader.get('coded-item'));
        },
        render: function (eventName) {
            $(this.el).html(this.template(this.model.toJSON()));
            return this;
        }
    });
    
    链接地址: http://www.djcxy.com/p/48320.html

    上一篇: 从收藏中移除时从视图中删除项目

    下一篇: 在backbone.js中共享视图之间的模型