【发布时间】:2014-09-11 07:45:42
【问题描述】:
我一直在寻找更新路由模型的机制,并让组件(从与该路由关联的模板中调用)对该事件做出反应,并重新渲染自身。
所以我有这样的索引模板(我传入了 IndexController 的模型,据我了解,这只是 IndexRoute 的代理——顺便说一下,我没有定义 IndexController):
<script type="text/x-handlebars" id="index">
Below is the bar-chart component
<br/>
{{bar-chart model=model}}
</script>
我的组件模板是这样的:
<script type="text/x-handlebars" data-template-name="components/bar-chart">
</script>
我的组件是在一个单独的 JS 文件中实现的,像这样:
App.BarChartComponent = Ember.Component.extend({
classNames: ['chart'],
model: null,
chart: BarChart(),
didInsertElement: function() {
Ember.run.once(this, 'update');
},
update: function() {
var data = this.get('model').map(function(sales) {
return sales.get('amount');
});
d3.select(this.$()[0]).selectAll('div.h-bar')
.data(data)
.call(this.get('chart'));
}
});
BarChart() 函数只是返回一个函数对象,该函数对象执行 DOM 操作以使用 D3 生成图形。
我的 IndexRoute 是这样定义的:
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('sales');
}
});
在这个实验中,我使用了fixture:
App.Sales = DS.Model.extend({
amount: DS.attr('number')
});
idx = 1;
App.Sales.FIXTURES = [
{id: idx++, amount: 2}, {id: idx++, amount: 6}, {id: idx++, amount: 12},
{id: idx++, amount: 17}, {id: idx++, amount: 8}
];
我需要实现一种机制来定期轮询 store 并更新 Route 的模型,并让 EmberJS 的魔法再次调用渲染函数(分配给 BarChart 组件中“chart”字段的值)。
这样做的正确方法是什么?我一直在尝试使用setInterval并调用Route的refresh()方法,但目前还没有成功。
感谢您的帮助!, 拉卡
添加(我在此处添加了关于格式的附加评论)。
我在 app.js 中添加了对 setInterval 的调用,如下所示:
setInterval(function () {
App.Sales.FIXTURES.shift();
App.Sales.FIXTURES.push({
id: idx++,
amount: Math.round(Math.random() * 20)
});
App.IndexRoute.refresh();
}, 1500);
但我收到 JavaScript 错误,告诉我 App.IndexRoute 未定义。我打算在 Route 对象上调用“刷新”方法,因为我希望重新执行模型挂钩。如何从我的 setInterval 函数中获取对 IndexRoute 实例的引用?
顺便说一句,这是触发刷新的正确/最佳方式吗?
(并且,根据下面 Oliver 的建议,我还在控制器中的“更新”函数中添加了观察(“模型”)。所以现在是这样的:
App.BarChartComponent = Ember.Component.extend({
classNames: ['chart'],
model: null,
chart: BarChart(),
didInsertElement: function() {
...
},
update: function() {
...
}.observes('model')
});
ADDITION 2(回复EmberJS, polling, update route's model, re-render component)
知道了!谢谢。
现在对于更新用例(后端中的元素数量保持不变,id 保持不变,只有“数量”随时间变化)。我将 setInterval 块修改为:
setInterval(function () {
App.Sales.FIXTURES.forEach(function(elem) {
elem.amount = elem.amount + 5;
});
console.log('z');
}, 1500);
现在的问题是,BarChartComponent 中观察“model.@each”的“update”方法永远不会被调用(好像我在夹具元素中所做的更改没有被 BarChartComponent 听到)。
我需要添加哪些指令?
附加 3(EmberJS, polling, update route's model, re-render component 的详细信息):
我在我的代码中添加了 IndexController 的定义,只是为了确认我对 FIXTURE 中元素的更改至少被控制器听到了(它是)。
所以,现在的问题是组件也能听到这种变化。如何?我应该从我的控制器调用一些“渲染”函数来要求组件重绘自己吗?
App.IndexController = Ember.ArrayController.extend({
totalAmount: function() {
console.log("iiii");
var total = 0;
this.forEach(function(sales) {
console.log("a... " + sales.get('amount'));
total += sales.get('amount');
});
return total;
}.property('@each.amount')
});
【问题讨论】:
-
在你的组件上不应该是
.observes('model')吗? -
您好,您的意思是在分配给“更新”字段的函数末尾添加“.observes('model')”?
-
所以您在索引控制器中的计算属性会更新,但您的组件中的某些属性不会?
-
嗨,解决了。在条形图组件中,我将观察修改为:model.@each.amount
标签: ember.js model controller routes refresh