Статьи

Начало в Ember.js: Часть 3

Я надеюсь, что вы начинаете понимать, что Ember.js является мощным, но самоуверенным фреймворком. Мы только поцарапали его поверхность; еще многое нужно узнать, прежде чем мы сможем создать что-то действительно полезное! Мы продолжим использовать Ember Starter Kit . В этой части серии мы рассмотрим доступ и управление данными в Ember.


В прошлой статье мы работали со статическим набором имен цветов, которые были определены в контроллере:

1
2
3
4
5
App.IndexRoute = Ember.Route.extend({
 setupController: function(controller) {
   controller.set(‘content’, [‘red’, ‘yellow’, ‘blue’]);
 }
});

Это позволило контроллеру выставить данные в шаблон индекса . Это мило для демонстрации, но в реальной жизни наш источник данных не будет жестко закодированным массивом.

Вот где приходят модели . Модели — это объектные представления данных, которые использует ваше приложение. Это может быть простой массив или данные, динамически извлекаемые из RESTful JSON API. Доступ к самим данным осуществляется путем ссылки на атрибуты модели. Итак, если мы посмотрим на результат, как это:

1
2
3
4
5
6
{
   «login»: «rey»,
   «id»: 1,
   «age»: 45,
   «gender»: «male»
}

Атрибуты, представленные в модели:

  • авторизоваться
  • Я бы
  • возраст
  • Пол

Доступ к самим данным осуществляется путем ссылки на атрибуты модели.

Как видно из приведенного выше кода, вы можете определить статическое хранилище, но вы будете использовать Ember.Object для определения ваших моделей большую часть времени. Подклассифицируя Ember.Object , вы сможете возвращать данные (например, через вызов Ajax) и определять свою модель. Несмотря на то, что вы можете явно устанавливать данные в контроллере, всегда рекомендуется создавать модель, чтобы придерживаться разделения проблем и передовых методов организации кода.

В качестве альтернативы, вы можете использовать родственный фреймворк Ember Data . Это ORM-подобный API и хранилище персистентности, но я должен подчеркнуть, что на момент написания статьи он находился в состоянии постоянного изменения. У него большой потенциал, но в настоящее время использовать Ember.Object намного безопаснее. Робин Уорд, соучредитель Discourse , написал отличный пост в блоге об использовании Ember без Ember Data. В нем описывается их процесс, который я вам сломаю.


В следующем примере я собираюсь использовать неофициальный Hacker News API для извлечения данных на основе JSON из новостного ресурса. Эти данные будут сохранены в моей модели и позже использованы контроллером для заполнения шаблона. Если мы посмотрим на данные, возвращенные из API, мы сможем понять свойства, с которыми мы будем работать:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  «nextId»: null,
  «items»: [{
          «title»: «Docker, the Linux container runtime: now open-source»,
          «url»: «http://docker.io»,
          «id»: 5445387,
          «commentCount»: 39,
          «points»: 146,
          «postedAgo»: «2 hours ago»,
          «postedBy»: «shykes»
      }, {
          «title»: «What\u0027s Actually Wrong with Yahoo\u0027s Purchase of Summly»,
          «url»: «http://hackingdistributed.com/2013/03/26/summly/»,
          «id»: 5445159,
          «commentCount»: 99,
          «points»: 133,
          «postedAgo»: «2 hours ago»,
          «postedBy»: «hoonose»
      },
  ],
  «version»: «1.0»,
  «cachedOnUTC»: «\/Date(1364333188244)\/»
}

Я хочу работать со свойством items , которое содержит все заголовки и информацию об истории. Если вы работали с базами данных SQL, рассматривайте каждый элемент items как запись, а имена свойств (т. url , url , id и т. Д.) Как имена полей. Важно отказаться от макета, потому что эти имена свойств будут использоваться в качестве атрибутов объекта нашей модели, что является идеальным способом создания модели.

Ember.Object является основным базовым классом для всех объектов Ember, и мы создадим его подкласс для создания нашей модели с использованием метода Ember.Object extend() .

Для этого мы добавим следующий код в js / app.js сразу после кода, который определяет App.IndexRoute :

1
App.Item = Ember.Object.extend();

App.Item служит классом модели для данных Hacker News, но у него нет методов для извлечения или манипулирования App.Item данными. Итак, нам нужно определить их:

01
02
03
04
05
06
07
08
09
10
11
12
13
App.Item.reopenClass({
  all: function() {
      return $.getJSON(«http://api.ihackernews.com/page?format=jsonp&callback=?»).then(function(response) {
        var items = [];
 
        response.items.forEach( function (item) {
          items.push( App.Item.create(item) );
        });
 
          return items;
      });
  }
});

Давайте разберем этот код. Сначала мы используем метод reopenClass() Ember, чтобы добавить наши новые методы в класс App.Item , и вы передаете ему объект, который содержит наши нужные методы. Для этого примера нам нужен только один метод с именем all() : он возвращает все заголовки с главной страницы Hacker News. Поскольку jQuery является частью сделки с Ember, у нас есть простой Ajax API. API использует JSONP для возврата данных JSON; поэтому я могу просто использовать $.getJSON() чтобы сделать запрос:

1
$.getJSON(«http://api.ihackernews.com/page?format=jsonp&callback=?»)

«Обратный звонок =?» сообщает jQuery, что это запрос JSONP, и данные (после их получения) передаются в анонимный обработчик обратного вызова, определенный с помощью функции обещаний jQuery:

1
.then(function(response) {…});

Я легко могу вставить свои данные JSON в объект Ember.

Параметр response содержит данные JSON, позволяя вам перебирать записи и обновлять массив локальных items экземплярами App.Item . Наконец, мы возвращаем вновь заполненный массив при выполнении all() . Это много слов, поэтому позвольте мне подвести итог:

  • Создайте свой новый класс модели, Ember.Object подкласс Ember.Object с помощью extend() .
  • Добавьте методы вашей модели, используя reopenClass() .
  • Сделайте Ajax-вызов, чтобы получить ваши данные.
  • Зацикливайте свои данные, создавая объект Item и помещая его в массив.
  • Вернуть массив при выполнении метода.

Если вы обновите index.html , вы увидите, что ничего не изменилось. Это имеет смысл, потому что модель была только определена; мы не получили к нему доступ.


Контроллеры действуют как прокси, предоставляя вам доступ к атрибутам модели и позволяя шаблонам получать к ним доступ для динамической визуализации отображения. Помимо доступа к атрибутам из связанной модели, контроллеры также могут хранить другие свойства приложения, которые должны сохраняться без сохранения на сервере.

В настоящее время наше приложение имеет следующий контроллер (тот, который определяет статический набор данных):

1
2
3
4
5
App.IndexRoute = Ember.Route.extend({
  setupController: function(controller) {
    controller.set(‘content’, [‘red’, ‘yellow’, ‘blue’]);
  }
});

Мы можем напрямую связать нашу модель с App.IndexRoute используя метод model (AKA the hook модели):

1
2
3
4
5
App.IndexRoute = Ember.Route.extend({
  model: function() {
    return App.Item.all();
  }
});

Помните, что Ember определяет ваш контроллер, если вы сами не определяете его, и именно это происходит в этом случае.

За кулисами Ember создает IndexController как экземпляр Ember.ArrayController и использует модель, указанную в методе model .

Теперь нам просто нужно обновить шаблон индекса, чтобы получить доступ к новым атрибутам. Открыв index.html , мы увидим следующий код шаблона Handlebars:

1
2
3
{{#each item in model}}
    <li>{{item}}</li>
{{/each}}

С одним небольшим изменением (добавив свойство title ) мы сразу можем увидеть заголовки, возвращенные из Hacker News API:

{{item.title}}

Если вы обновите свой браузер сейчас, вы должны увидеть что-то похожее на следующее:

1
2
3
4
5
6
<h3>Welcome to Ember.js</h3>
<ul><li>Persona is distributed.
<li>21 graphs that show America’s health-care prices are ludicrous</li>
<li>10 000 concurrent real-time connections to Django</li>
<li>Docker, the Linux container runtime: now open-source</li>
<li>Let’s Say FeedBurner Shuts Down…</li></ul>

Если вы хотите отобразить больше информации, просто добавьте больше свойств:

1
{{item.title}} — {{item.postedAgo}} by {{item.postedBy}}

Обновите, чтобы увидеть обновления, которые вы сделали. Это красота руля; это делает тривиальным добавление новых элементов данных в пользовательский интерфейс.

Как я упоминал ранее, контроллеры также могут использоваться для определения статических атрибутов, которые должны сохраняться в течение всего жизненного цикла вашего приложения. Например, я хочу сохранить определенный статический контент, например:

1
2
3
4
App.IndexController = Ember.ObjectController.extend({
  headerName: ‘Welcome to the Hacker News App’,
  appVersion: 2.1
});

Здесь я подкласс Ember.ObjectController чтобы создать новый контроллер для моего индекса маршрута и шаблон для работы. Теперь я могу перейти к index.html и обновить мой шаблон, чтобы заменить следующее:

1
<h2>Welcome to Ember.js</h2>

с:

1
<h2>{{headerName}}</h2>

Модели — это объектные представления данных, которые использует ваше приложение.

Рули будут принимать указанные атрибуты в моем контроллере и динамически заменять заполнитель {{headerName}} его значением тезки. Важно усилить две вещи:

  • Придерживаясь соглашений об именах Ember, мне не нужно было выполнять какие-либо подключения, чтобы иметь возможность использовать контроллер с шаблоном индекса.
  • Несмотря на то, что я явно создал IndexController , Ember достаточно умен, чтобы не перезаписывать существующую модель, связанную с маршрутом.

Это довольно мощный и гибкий материал!


Работать с данными в Ember не сложно. В действительности, самая сложная часть — это работа с различными API-интерфейсами, которые имеются в сети.

Тот факт, что я могу легко вставить свои данные JSON в объект Ember, значительно упрощает управление, хотя я никогда не был большим поклонником больших наборов данных на стороне клиента, особенно когда они представлены в виде объектов.

Это то, что мне нужно сделать для дальнейшего тестирования, и я надеюсь, что Ember Data сделает все это тривиальным.

С учетом сказанного я кратко коснулся шаблонов в этой статье. Они очень важны … настолько, что я хочу заняться этой темой в своей статье. Итак, в следующей статье мы рассмотрим, как использовать Handelbars для создания вашего пользовательского интерфейса и подробно рассмотрим различные директивы, которые предлагает шаблонная структура.