我正在学习JavaScript和backbone.js并尝试开发一个小型的Web应用程序。 但问题是我的页面(图形)会多次重载(超过预期)。因此,在页面稳定并显示图形之前,页面会自动重新加载(超快)。当我说“重新加载浏览器”时,我的意思是说谷歌浏览器刷新图标的重新加载图标会多次刷新/(正向旋转,向后旋转),最后显示数据。
以下是我迄今为止尝试过的简短版本。由于我处于学习阶段,我可能没有制定正确的编码标准。跟我一起承担。
所以,我必须在首页上显示一个图表(稍后我需要在同一页面上添加更多图表)。该图的数据来自REST服务。
HTML:
我有一个锚点和一个模板来显示图表数据。
<div id ="chartAnchor1"></div>
<script id="myChart-template" type="text/template">
<canvas id="lineChart"></canvas>
</script>
ViewModel
这是针对图表特定的数据:
var firstSubViewModel = Backbone.View.extend({
template: _.template($('#myChart-template').html()),
events: {
'click .Refresh': 'fetchModelData'
},
fetchModelData: function() {
this.model.initialize();
},
render: function()
{
$(this.el).html(this.template());
var ctx = $(this.el).find('#lineChart')[0];
var lineChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
datasets: [{
data: this.model.attributes.incThisYear
}, {
data: this.model.attributes.incLastYear
}]
},
labelString: 'Income in $'
}
}]
}
}
});
},
initialize: function() {
_.bindAll(this, "fetchModelData");
this.model.on('change', this.render, this);
}
});
return firstSubViewModel;
});
控制器:
var ch = new dashboardModel.chart({});
if (// some condition) {
var data = { // some data};
ch.fetch(data)
}
//Main Graph on Dashboard
new firstSubViewModel({
el: '#chartAnchor1',
model: ch
});
});
型号: 我有一个模型类从REST服务获取数据。
问题:页面刷新了大约5-6次,最后图形被完全加载。
FootNote:我的渲染功能有问题吗?请指导。
答案 0 :(得分:1)
您已使用this.model.on('change', this.render, this);
将模型的更改事件绑定到视图的渲染方法,这意味着对于模型的每次更改,视图都将重新渲染。
您将模型属性直接传递给某些Chart()
函数。我们不知道它内部发生了什么,但很可能它作为图表绘制的一部分多次更新模型属性,显然每次更改都会导致另一个render
调用{ {1}}方法再次调用Chart()
,因此创建一个渲染循环,可能与render
函数对模型所做的更改次数一样长。
删除Chart()
或使用模型的toJSON()
方法获取副本的数据并将其传递给this.model.on('change', this.render, this);
绘图方法。像这样的用例是chart()
方法存在的原因。
另一个问题是处理异步toJSON()
,我认为fetch
是你尝试处理这个问题,但这是错误的。要么你应该听取this.model.on('change', this.render, this);
之类的事件,比如
sync
或做类似的事情:
this.model.on('sync', this.render, this);
除此之外,您不应手动初始化模型。它是Backbone.js处理的一次性活动,只应在其中添加一次初始化代码。我甚至无法通过在已经初始化的模型上手动调用var ch = new dashboardModel.chart({});
/* ---------------------------^ this is the actual model constructor?
Then what's dashboardModel?! Bad naming ;) */
ch.fetch({
success: function(model, response) {
new firstSubViewModel({
el: '#chartAnchor1',
model: ch
});
}
});
来考虑您要实现的目标。
要从持久层获取数据,您应该使用initialize
方法。
fetch()
您在控制器中的代码有很多问题。它似乎尝试fetchModelData: function() {
this.model.fetch({/* options */});
}
带有数据的模型?,但fetch()
方法只接受选项,主要用于自定义和处理AJAX调用就像我上面使用过的那些(也许它们实际上是选项,但你把它命名为 data ?!在这种情况下忽略这个选项。)
此外还有一个视图,其中没有清理引用,通过fetch
选项直接引用DOM,如果您创建另一个el
实例,则会导致问题,使用{{ 1}}而不是listenTo
等所有导致经典的Backbone.js错误,如内存泄漏,事件等问题。
所有这些都无法在答案中处理,因此我建议您正确阅读文档并对常见的Backbone.js问题进行一些研究。
附注:根据常见的命名转换,firstSubViewModel
应为on
,因为它是构造函数。