Ember.Component http://emberjs.com/api/classes/Ember.Component.html是你的朋友
正如 @raulbrito 已经提到的,如果你想要 ember 中的可重用组件,最好的方法确实是使用新的Ember.Component
这在很大程度上基于Web 组件的新 w3 草案 http://www.w3.org/TR/2013/WD-components-intro-20130606/从而成为未来的证明。
我试图举一个简单的例子来说明如何实现这一点。
给定一个简单的route
哪里的model
钩子返回一些静态数据:
索引路线
App.IndexRoute = Ember.Route.extend({
model: function(){
return Ember.Object.create({
modelOne: data,
modelTwo: data2
});
}
});
data
and data2
为简单起见,只是全局定义的静态对象(正如你将看到的在演示中 http://jsbin.com/odosoy/146/edit),但这也可能是来自后端或固定装置等的数据。
索引模板
在模板中,我们插入带有线条的图表组件{{line-chart data=model.modelOne}}
正如你所看到的,我们还设置了data
索引模型的属性model.modelOne
or model.modelTwo
:
<script type="text/x-handlebars" id="index">
<h2>Chart one</h2>
{{line-chart data=model.modelOne}}
<h2>Chart two</h2>
{{line-chart data=model.modelTwo}}
</script>
组件模板
我们的组件模板看起来相当简单,因为它将呈现一个简单的canvas
元素,但它可以根据需要而复杂,关于如何使用Ember.Component
另请参阅docs http://emberjs.com/guides/components/:
<script type="text/x-handlebars" id="components/line-chart">
</script>
组件子类
App.LineChartComponent = Ember.Component.extend({
tagName: 'canvas',
attributeBindings: ['width', 'height'],
width: '480',
height: '360',
data: null,
didInsertElement: function() {
var ctx = this.get('element').getContext("2d");
var myNewChart = new Chart(ctx).Line(this.get('data'));
}
});
请注意,命名在这里很重要,Ember 根据名称知道哪个子类为组件提供支持。例如,如果您有一个名为line-chart
,您将创建一个名为的子类App.LineChartComponent
。如果你的组件被调用bar-chart-simple
,类名是App.BarChartSimpleComponent
等等。 Ember 将查找具有组件的驼峰名称的类,然后是Component
.
所以,自从Ember.Component
延伸自Ember.View
我们可以定义各种属性Ember.View
支持喜欢tagName
。在我们的例子中,我们使用canvas
因为这就是chart.js
需要工作。正如你所看到的,我们还定义了一些attributeBindings
来控制width
and height
of the canvas
从余烬内部。该组件还有一个data
属性(可以随意称呼)定义我们稍后在从返回的模板中设置模型数据IndexRoute
model
钩。最后在你的didInsertElement
我们组件的钩子我们初始化图表传递this.get('data')
新创建的数据对象Chart.js
class.
var ctx = this.get('element').getContext("2d");
var myNewChart = new Chart(ctx).Line(this.get('data'));
最后但并非最不重要的一点是,请参阅此处工作示例 http://jsbin.com/odosoy/146/edit以上的解释。
希望能帮助到你。
更新以回应您的最新评论
我试图模拟分辨率的延迟model
钩子来模仿后端的响应,正如您所看到的,模板渲染正在等待model
承诺先解决。基本上我所做的是使用Ember.run.later
延迟 2000 毫秒,一旦超时即可解决承诺:
App.IndexRoute = Ember.Route.extend({
model: function(){
return new Ember.RSVP.Promise(function(resolve) {
Ember.run.later(function() {
var m = Ember.Object.create({
modelOne: data,
modelTwo: data2
});
resolve(m);
}, 2000);
});
}
});
只是为了好玩我还添加了一个LoadingRoute
在承诺解析等待数据时显示旋转器,LoadingRoute
是 ember 的一个记录较少的功能,您可以在这里阅读更多相关信息:https://gist.github.com/machty/5647589 https://gist.github.com/machty/5647589 under 如何在带有 Promise 的转换过程中设置(全局)加载微调器?
请参阅此处的更新示例:http://jsbin.com/odosoy/145/edit http://jsbin.com/odosoy/145/edit
更新响应 @SamSelikoff 的评论
至于上面提到的LoadingRoute
@SamSelikoff 指出现在已正式记录:http://emberjs.com/guides/routing/defining-your-routes/#toc_initial-routes http://emberjs.com/guides/routing/defining-your-routes/#toc_initial-routes