【问题标题】:Sharing a model between views in backbone.js在backbone.js 中的视图之间共享模型
【发布时间】:2013-07-30 01:15:10
【问题描述】:

我正在使用backbone.js 开发一个phonegap 应用程序。我有以下型号:

  1. 一个措施
  2. 度量集合(主视图的基础)
  3. 代码
  4. 代码集合(Measure 的子级)

然后我有以下观点

  1. 主页
  2. 措施列表
  3. 测量页面
  4. 代码列表页面 (codedOptionsPage)(包括一个标题和一个作为列表容器的 div)
  5. 代码列表集合视图(codedItemListView,管理上面页面中的列表)
  6. 代码项(codedItemView - 每个列表项一个)

我希望 Measure 对象成为所有视图 3 - 6 的模型,以便在发生任何变化时,我可以更新主对象并保存它。

以下代码中发生的情况是,在第一次渲染 codedOptionsPage 时,“this.model”是 Measure 模型的一个实例。但是,在通过向 Measure 的代码集合中添加代码触发的后续渲染调用中,“this.model”是对原型的引用,而不是实例,因此我收到一条错误消息“Object function (){ return parent.apply (this, arguments); } 没有方法 'toJSON'"

我很确定下面的代码不是应该的,因为我仍在努力通过这种方法,我很乐意接受一般性建议,但我特别想知道模型发生了什么。

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;
    }
});

感谢收看!

【问题讨论】:

  • 在Measure Model中传递给View的代码在哪里.. 另外你能解释一下add方法和this.model.attributes.codes.bind('add', this.render);
  • 此外,使用attributes.name 访问属性也不是一个好主意。使用this.model.attributes.codes 而不是this.model.get('codes')

标签: backbone.js cordova


【解决方案1】:

这可能无法解决您的问题,但我建议您进行一些更改以使您的代码更清晰。

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;
    }
});

【讨论】:

  • @sydneyos.. 很高兴能帮上忙 :)
猜你喜欢
  • 2013-09-21
  • 1970-01-01
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 2017-01-14
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多