【问题标题】:Backbone collection empty when method called via change event通过更改事件调用方法时骨干集合为空
【发布时间】:2014-10-17 17:09:32
【问题描述】:

马上开始:这是我的第一个 Backbone 应用程序,所以如果有任何设计缺陷,我会全力以赴。此应用程序的目的是根据更改的输入值绘制/重新绘制条形图。

输入值存储在SliderModel 中。 DataSeries 集合中的每个 DataPoint 模型应该代表在 BarGraph 视图中绘制的一列数据。

当用户更改SliderModel 中的值时,我在BarGraph 中绑定了事件处理程序方法,以便我可以根据输入动态重新绘制图形。

当页面加载时,BarGraph 视图中的updateCalculations 方法会运行。计算得到正确处理,图形被正确绘制(全为零)。

但是,一旦用户开始输入输入(即单个字符),下面的other 变量(来自视图中的updateCalculations 方法)被评估为undefined

var other = this.collection;

由于某种原因,当通过更改SliderModel 属性调用updateCalculations 方法时,BarGraph 视图中的collection 将被清除。

型号

包含默认值和计算方法的模型

var SliderModel = Backbone.Model.extend({
    initialize: function() {

    },

    defaults: {
        purchasePayment: '0',
        fixedRate: '0',
        returnSpx: '0',
        slidervalue: '0'
    },

    fixedAllocation: function () {
        return this.attributes.purchasePayment * (1 - (this.attributes.slidervalue / 100));
    },

    illustratedEoy: function() {
        return this.fixedAllocation() * Math.pow(1 + (this.attributes.fixedRate / 100), 7);
    },

    eoyContractVal: function (value) {
        return this.illustratedEoy() + parseFloat(value);
    }
});

型号/系列

集合和集合的模型类型

var DataPoint = Backbone.Model.extend({

    initialize: function (lbl, ctrct, rtrn) {
        this.set({
            label: lbl,
            contract: ctrct,
            annReturn: rtrn
        })
    },
});

var DataSeries = Backbone.Collection.extend({

    model: DataPoint,

    fetch: function () {
        this.reset();
        this.add([
            new DataPoint("1/7yrs", "111830.17", "1.63%"),
            new DataPoint("2/7yrs", "115311.17", "2.07%"),
            new DataPoint("3/7yrs", "118984.65", "2.52%"),
            new DataPoint("4/7yrs", "122859.65", "2.98%"),
            new DataPoint("5/7yrs", "126947.77", "3.46%"),
            new DataPoint("6/7yrs", "131260.74", "3.94%"),
            new DataPoint("7/7yrs", "135810.92", "4.44%")
        ])
    }
});

查看

SliderModel 是分配给此视图的模型。 DataSeries 是分配给视图的集合。

var BarGraph = Backbone.View.extend({

    "el": "#graph",

    options: {barDemo: ""},

    initialize: function (options) {

        _.bindAll(this, "render");
        this.collection.bind("change", this.updateCollection);

        //Bind model change event to view event handler
        this.model.bind('change:purchasePayment', this.updateCollection);
        this.model.bind('change:slidervalue', this.updateCollection);
        this.model.bind('change:purchasePayment', this.updateCollection);
        this.model.bind('change:slidervalue', this.updateCollection);
        this.model.bind('change:fixedRate', this.updateCollection);
        this.model.bind('change:returnSpx', this.updateCollection);

        //Run setup methods
        this.drawGraph();
        this.collection.fetch();
        this.updateCollection();
    },

    drawGraph: function() {
        var margin = { top: 20, right: 20, bottom: 20, left: 20 };

        this.options.barDemo = d3.selectAll($(this.el)).append("svg:svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom + 20);
    },

    updateCollection: function () {
        var sum = 0.00;
        var that = this.model;

        //Collection shows as 'undefined' when this method is fired via change event
        var other = this.collection;

        var indexed = $.makeArray($('#IndexedTable').find('tbody tr'));

        var i = 0;
        this.collection.each(function (m) {
            var value = that.eoyContractVal(that.indexedIllustrated(i));
            sum = parseFloat(sum) + parseFloat(value);

            other.models[i].attributes.contract = value.toFixed(2);
            other.models[i].attributes.annReturn = that.annReturn(value).toFixed(2) + '%';
            i++;
        });

        this.render();
    },

    render: function () {

    },
});

jQuery

上面的代码是如何初始化的

var sliderModel = new SliderModel;
var dataSeries = new DataSeries();
new BarGraph({
    collection: dataSeries,
    model: sliderModel
});

【问题讨论】:

  • 我不知道为什么集合是未定义的,但是您有一个转机解决方案,您可以像这样从模型访问集合:var other = this.model.collection,否则如果您可以创建一个jsfiddle,方便我们看问题

标签: javascript jquery backbone.js


【解决方案1】:

首先,覆盖原始 Collection 方法(如 fetch)是个坏主意。你不需要那个。

如果您想在不转到服务器的情况下添加一些测试数据,请在集合定义之外使用reset 方法或add

http://backbonejs.org/#Collection-reset

我将只留下model 属性的集合。在您的“主”(您的 jQuery 就绪处理程序)中,填写数据:

var slider = new SliderModel();
var dataSeries = new DataSeries();
var view = new BarGraph({
  model: slider,
  collection: dataSeries
});


dataSeries.reset([
  new DataPoint("1/7yrs", "111830.17", "1.63%"),
  new DataPoint("2/7yrs", "115311.17", "2.07%"),
  new DataPoint("3/7yrs", "118984.65", "2.52%"),
  new DataPoint("4/7yrs", "122859.65", "2.98%"),
  new DataPoint("5/7yrs", "126947.77", "3.46%"),
  new DataPoint("6/7yrs", "131260.74", "3.94%"),
  new DataPoint("7/7yrs", "135810.92", "4.44%")
]);

现在在您的视图中,您正在收听集合中的 change 事件,但这是一个模型事件。 http://backbonejs.org/#Events-catalog

通常首选监听reset 事件,您可以像我们刚才那样自行触发重置集合,或者调用collection.fetch({reset:true}) 从服务器获取数据。

建议使用listenTo 函数进行事件处理,因为它会自动将函数上下文绑定到当前对象。 http://backbonejs.org/#Events-listenTo

所以你的初始化方法变成了:

initialize: function (options) {

  _.bindAll(this, "render");
  this.listenTo(this.collection, "reset", this.updateCollection);

  //Bind model change event to view event handler
  //instead of individually listen to every attribute change
  //just listen to any change in one line
  this.listenTo(this.model, "change", this.updateCollection);

  //Run setup methods
  this.drawGraph();
  //not needed with fake data... or save it to a JSON file and fetch it!
  //this.collection.fetch();
  this.updateCollection();
}

【讨论】:

  • 对于他的项目,我不需要任何服务器请求,只需操作页面上的数据(这是一个费率计算器)。既然如此,我想简单地将 fetch 方法设置为首先调用this.reset(),然后将 5 个空白DataPoints 添加到集合中,还是有更清洁/更好的实践方法?
  • 但重点是,为什么要重写一个方法?正如我的代码所示,它已经存在并且被称为reset。你试过了吗?
  • 我想我可能还没有完全理解reset 所涉及的内容。它不会清除集合,因此它的模型总数为 0?
  • 可以,但您也可以添加新模型,如我的示例所示。
猜你喜欢
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多