Ответ 1
Ember.Component
- ваш друг
Как уже упоминалось в @raulbrito, лучший способ пойти, если вы хотите использовать повторно используемые компоненты в ember, действительно должен использовать новый Ember.Component
, который в значительной степени основан на новом проекте w3 для веб-компонентов и, таким образом, будущих доказательств.
Я попытался сделать простой пример того, как это можно реализовать.
Учитывая простой route
, где hook model
возвращает некоторые статические данные:
Маршрут указателя
App.IndexRoute = Ember.Route.extend({
model: function(){
return Ember.Object.create({
modelOne: data,
modelTwo: data2
});
}
});
data
и data2
являются просто статическими объектами, глобально определенными для простоты (как вы увидите в демонстрации), но это могут быть также данные, поступающие из бэкэнд или из светильников и т.д.
Шаблон индекса
В шаблоне мы вставляем наш компонент диаграммы в строку {{line-chart data=model.modelOne}}
, и, как вы можете видеть, мы также устанавливаем атрибут data
в индексную модель model.modelOne
или 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
, пожалуйста, обратитесь к документы:
<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
и height
canvas
изнутри ember. Компонент также имеет атрибут 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'));
И последнее, но не менее важное: см. здесь рабочий пример описанного выше.
Надеюсь, что это поможет.
Обновление в ответ на ваш последний комментарий
Я попытался смоделировать задержку в разрешении model
hook, чтобы имитировать ответ из бэкэнд, так как вы можете видеть, что рендеринг шаблона ожидает, когда обещание 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 в разделе Как разместить (глобальную) загрузку Spinner во время перехода w/ Promises?
Plase см. здесь для обновленного примера: http://jsbin.com/odosoy/145/edit
Обновление в ответ на комментарий @SamSelikoff
Что касается вышеупомянутого LoadingRoute
@SamSelikoff, он отметил, что он официально документирован сейчас: http://emberjs.com/guides/routing/defining-your-routes/#toc_initial-routes