所以我有这样的索引模板(我传入了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'); } });
在这个实验中,我使用夹具:
App.Sales = DS.Model.extend({ amount: DS.attr('number') }); idx = 1; App.Sales.FIXTURES = [ {id: idx++,amount: 2},{id: idx++,amount: 6},amount: 12},amount: 17},amount: 8} ];
我需要实现一个机制来定期轮询存储并更新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对象上调用’refresh’方法,因为我希望重新执行模型钩子.如何从setInterval函数获取对IndexRoute实例的引用?
这是触发刷新的正确/最佳方式,顺便说一下?
(并且,根据下面的Oliver的建议,我还在控制器中的’update’函数中添加了观察(‘model’).所以现在就是这样:
App.BarChartComponent = Ember.Component.extend({ classNames: ['chart'],didInsertElement: function() { ... },update: function() { ... }.observes('model') });
附加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,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') });
解决方法
对于您的特定情况,此处需要注意一些重要事项,find(‘type’)返回所有过滤器,当您从商店添加/删除项目时,该过滤器会自动更新.所以你可以在代码中的任何地方再次调用find(对于那种类型),它会自动更新你的集合.此外,您还希望控制路由级别的更新,这样您就不会在不在范围内时继续更新.
App.IndexRoute = Ember.Route.extend({ model: function() { return this.store.find('sales'); },setupController: function(controller,model){ this._super(controller,model); // do the default implementation since I'm overriding this func this.startRefreshing(); },startRefreshing: function(){ this.set('refreshing',true); Em.run.later(this,this.refresh,30000); },refresh: function(){ if(!this.get('refreshing')) return; this.store.find('sales') Em.run.later(this,actions:{ willTransition: function(){ this.set('refreshing',false); } } });
示例:http://emberjs.jsbin.com/OxIDiVU/825/edit
此外,对于组件,您需要观察数组,而不仅仅是模型本身(因为模型引用不会更新,这意味着不会调用观察方法).你会做这样的事情
watchingForModelChange: function(){ }.observes('model.[]')