ember中可重用对象的体系结构

Tho*_*s K 13 ember.js

我正在使用ember构建管理仪表板.我想创建一个可重用的图表对象,我可以在整个应用程序中拥有多个实例.图表对象应该有一个模板,该模板由一些标记和一个canvas元素组成,我在DOM中插入后需要id才能附加实际图表(chart.js).我尝试了几种方法,但我似乎无法找到正确的架构来做到这一点.

在实现上述目标的过程中,什么是正确的体系结构?

谢谢!

int*_*xel 34

Ember.Component 是你的朋友

正如@raulbrito已经提到的,如果你想在ember中使用可重用组件,最好的方法就是使用新的Ember.Component,它基于新的w3草案用于Web组件,从而成为未来的证明.

我试图用一个简单的例子来说明如何实现它.给定一个简单routemodel钩子返回一些静态数据:

索引路线

App.IndexRoute = Ember.Route.extend({
  model: function(){
    return Ember.Object.create({
      modelOne: data,
      modelTwo: data2
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

data并且data2只是为了简单而全局定义的静态对象(正如您将在演示中看到的那样),但这也可能是来自后端或来自灯具等的数据.

索引模板

在模板中,我们将我们的图表组件插入到该行中{{line-chart data=model.modelOne}},如您所见,我们还将该data属性设置为索引模型model.modelOnemodel.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>
Run Code Online (Sandbox Code Playgroud)

组件模板

我们的组件模板看起来相当简单,因为它将呈现一个简单的canvas元素,但它可能会根据需要变得复杂,如何使用Ember.Component请参阅文档:

<script type="text/x-handlebars" id="components/line-chart">
</script>
Run Code Online (Sandbox Code Playgroud)

组件子类

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'));
  }
});
Run Code Online (Sandbox Code Playgroud)

注意命名在这里很重要,Ember知道哪个子类根据其名称为组件提供动力.例如,如果您有一个名为的组件line-chart,您将创建一个名为的子类App.LineChartComponent.如果调用bar-chart-simple了组件,则类名将为App.BarChartSimpleComponent依此类推.Ember将查找具有该组件的camelized名称的类,然后是Component.

所以,从Ember.Component扩展开始Ember.View我们就可以定义各种属性Ember.View支持了tagName.在我们的案例中,我们使用,canvas因为这是chart.js需要工作的.正如你所看到的,我们也定义了一些attributeBindings控制widthheightcanvas从内余烬.组件还有一个data属性(可以调用任何你认为合适的属性),我们稍后在IndexRoute model钩子返回的模板中设置模型数据.最后,在didInsertElement我们组件的钩子中,我们将使用this.get('data')数据对象传递的图表初始化为新创建的Chart.js类.

var ctx = this.get('element').getContext("2d");
var myNewChart = new Chart(ctx).Line(this.get('data'));
Run Code Online (Sandbox Code Playgroud)

最后但并非最不重要的是,请在此处查看上述解释的工作示例.

希望能帮助到你.

更新以回应您的上次评论

我试图模拟model钩子分辨率的延迟来模仿来自后端的响应,因为你可以看到模板渲染正在等待model承诺首先解决.基本上我所做的就是使用Ember.run.later延迟2000ms来解决一旦超时的承诺:

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);
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

而且为了好玩,我还添加了一个LoadingRoute显示微调器,而承诺解决方案正在等待数据,这LoadingRoute是一个较少记录的ember功能,你可以在这里阅读更多关于它:https://gist.github.com/ machty/5647589如何在转换w/Promises期间建立一个(全局)Loading Spinner?

请看这里的更新示例:http://jsbin.com/odosoy/145/edit

更新以回应@ SamSelikoff的评论

至于上面提到的LoadingRoute@SamSelikoff指出它现在正式记录:http://emberjs.com/guides/routing/defining-your-routes/#toc_initial-routes