Таким образом, вы приняли вызов, чтобы идти в ногу со стороны клиента; отлично сработано. Вы рассмотрели все фреймворки и не знаете, какой выбрать? Ты не одинок. Читай дальше.
Мой опыт, когда я изучаю способ написания клиентских приложений, оказывается крутым и сложным. Нелегко сознательно выбрать использование MV*
на клиенте для того, кто написал JavaScript, полностью основываясь на jQuery и его плагинах. Это совершенно новая парадигма; это требует базовых навыков программирования и глубокого понимания дизайна JavaScript (языка). Если ваш опыт относится к моему, то читайте дальше!
Я объясню основные различия между двумя из самых популярных клиентских сред JavaScript: Backbone.js и Ember.js . У каждого из этих инструментов есть как сильные, так и слабые стороны, которые могут помочь вам сделать более продуманный выбор.
Отказ от ответственности: как профессионалы в области программного обеспечения, мы должны иметь дело с разнообразием мнений. Backbone и Ember — это результаты авторитетных и опытных профессионалов, таких как вы и я. Один инструмент не лучше другого; они просто обслуживают разные толпы и, следовательно, решают разные проблемы. Спасибо Трек за твердый совет.
Философия
Магистраль гораздо легче выучить, чем Эмбер.
Прежде всего, вы должны понимать, что Backbone и Ember особенно служат немного разным толпам. Что касается сложности, Backbone гораздо легче выучить, чем Ember. Тем не менее, говорят, что как только вы изучите Ember, это вряд ли станет более сложным. Поверь на слово Трека . Если вы только начинаете работать с настоящим JavaScript, то, возможно, Backbone — ваш инструмент. Если, однако, вы знаете, что вы будете иметь дело с гораздо большим, чем просто один или два варианта использования, вы можете предпочесть Ember.
позвоночник
Джереми Ашкенас создал Backbone, чтобы можно было извлечь правду из DOM
. Под этим он подразумевает следующее: независимо от того, чем вы занимаетесь, используя только jQuery / Mootools / Prototype, можно и нужно лучше извлекать его в чистые структуры JavaScript — объекты, если хотите. Вместо использования элементов DOM
для определения ваших бизнес-элементов и поведения, Backbone предлагает вам сделать это наоборот. Объекты JavaScript — это ядро, а DOM
— просто представление этих данных.
С Backbone у вас есть несколько утверждений:
- Данные лежат в объектах JavaScript, а не в
DOM
- Обработка событий заключается в объектах JavaScript, а не в привязках событий jQuery.
- Способ сохранения данных на бэкэнд-сервере осуществляется с помощью объектов, которые содержат данные
Вы получаете полный контроль над тем, как вы строите свое приложение. Backbone предназначался для того, чтобы дать вам базовый способ проектирования объектов вашей модели и того, как они взаимодействуют друг с другом через привязки событий.
Рендеринг HTML
в DOM
— ваша ответственность. Вы можете выбрать любой движок шаблонов: Усы, DoT, Handlebars, Underscore и т. Д. Backbone содержит прототип View
, который отвечает за артикуляцию DOM
и вашего ядра JavaScript.
тлеющие угли
Когда Tilde начал создавать Ember, он сделал это с гораздо более сложной задачей: обеспечить стандартные соглашения в разработке на стороне клиента, устраняя как можно больше шаблонов . Результатом является гораздо более амбициозная структура, нацеленная на предсказуемую архитектуру и устойчивое развитие.
Ember разделяет некоторые общие черты с Backbone в том, как он пытается извлечь данные и поведение из DOM
, предоставляя расширяемые прототипы JavaScript, но делает это совершенно иначе, чем Backbone.
Эмбер стоит на:
- Двусторонняя привязка данных : объекты в Ember могут регистрировать привязки между собой. Таким образом, всякий раз, когда связанное свойство изменяется, другое обновляется автоматически.
- Вычисляемые свойства : если вы хотите иметь свойство, являющееся результатом функции, вы можете создать их и назначить свойство, вычисленное этой функцией.
- Автообновления шаблона : когда объект обновляется в вашем приложении, все представления, отображаемые в данный момент на экране, которые привязаны к этому объекту, автоматически отражают изменение, без шаблона.
ДОМ — Взгляды
И Backbone, и Ember имеют общие ключевые понятия, такие как представления . Они оба представляют связь DOM
, соответственно. Однако то, как они реализуют эту концепцию, несколько иное.
Я буду использовать сценарий использования Todo для приведенных ниже примеров, вдохновленных демонстрацией TodoMVC .
позвоночник
Вид Backbone может выглядеть примерно так:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
var TaskView = Backbone.View.extend({
tagName : «li»
, template : «task-template»
, render : function() {
// your code to render here.
}
, events : {
«click .mark-done» : «mark_as_done»
, «change .body» : «update_body»
}
, mark_as_done : function() { /* code here */ }
, update_body : function() { /* code here */ }
});
|
Это просто определение вашего взгляда. Вам нужно будет создать его экземпляр, если вы хотите, чтобы он был на странице. Нечто подобное сделает свое дело:
1
2
|
var task_view = new Task({ model : task_model });
$(«body»).append(task_view.el);
|
Обратите внимание, что мы передаем модель, чтобы вы могли сохранить ссылку на объект данных, который передает шаблон. Свойство template
внутри представления можно использовать для вызова внешнего шаблона через идентификатор. Я использовал что-то подобное в прошлом:
01
02
03
04
05
06
07
08
09
10
|
var TaskView = Backbone.View.extend({
template : «#task-template»
, render : function() {
this.$el.html(
Mustache.render($(this.template).html())
, this.model);
}
// snip
});
|
тлеющие угли
У Эмбер другой подход к взглядам. Фактически, соглашение гласит, что представления должны взаимодействовать с контроллерами, а не с моделями напрямую. Это хорошая практика, если вы собираетесь следовать стабильной архитектуре. Я объясню образец для того же представления:
1
2
3
4
5
|
var TaskView = Ember.View.extend({
templateName : «task-template»
, mark_as_done : function() { /* code here */ }
, update_body : function() { /* code here */ }
});
|
Вот и все. Но где все вещи рендеринга? Ну, Эмбер поднимает этот шаблон для тебя. Просто скажите, что это за шаблон, контроллер, который содержит объект данных, и тогда вам просто нужно добавить его в DOM
.
1
2
3
4
5
|
var task_view = TaskView.create({
controller : task_controller // Ember.ObjectController
});
task_view.append();
|
При создании нового экземпляра представления он связывает содержимое контроллера (которое может быть Ember.Object
или их списком) с представлением. Когда вы решите добавить представление в DOM
, он будет искать шаблон и размещать сгенерированную разметку для вас.
мысли
Магистраль более явная и менее волшебная.
Магистраль более явная и менее волшебная. Вы создаете View
, сообщаете ему, какой шаблон использовать и как, регистрируете события и делаете то, что должны делать. Они владеют страницей. Это отличное начало для тех, кто пришел из jQuery. Однако, когда что-то нужно обновить в DOM
, вы столкнетесь с некоторыми шаблонами.
С Ember обновления выполняются автоматически. Вы говорите, что это за шаблон, и обратные вызовы событий являются функциями внутри объекта представления. Каждый раз, когда объект обновляется, представление автоматически обновляет страницу.
Некоторые общие привязки событий встроены в Ember, а другие должны быть помещены в шаблон. Это хорошо для тех, кто приходит с бэкэнд-перспективы, так как это значительно уменьшает шаблон.
Данные — Модели
Модели в Backbone и Ember довольно похожи. Они содержат информацию для бизнес-объекта.
позвоночник
Пример модели Backbone выглядит следующим образом:
1
|
var TaskModel = Backbone.Model.extend();
|
С этой простой строкой кода у вас есть работающая модель со встроенной связью REST
. Вы получаете такие методы, как save
чтобы сохранить данные и fetch
их бесплатно; плагин не требуется. Проверка также встроена в способ сохранения данных путем предоставления обратного вызова validate
, который возвращает логическое значение, указывающее, сохранять запись или нет. Внедрение проверки все еще остается за разработчиком.
Чтобы создать новую задачу, вы TaskModel
новую TaskModel
.
1
2
3
4
|
var task = new TaskModel({
body : «Mow the lawn»
, done : false
});
|
Вы можете добавить столько атрибутов, сколько хотите, потому что список атрибутов задачи не является строгим (представьте, что он не имеет схемы ). Вы все еще можете установить свойство по defaults
при расширении Backbone.Model
.
тлеющие угли
С Ember нет моделей, только объекты. Это может выглядеть примерно так:
1
|
var TaskObject = Ember.Object.extend();
|
Как и в Backbone, вам нужно расширить Ember.Object
для создания класса объекта. Он наследует все основные функциональные возможности для класса с обратными вызовами, когда он изменяется, создается и уничтожается, среди других функций. Однако он не имеет внутренней связи из коробки. Ember.Data
разрабатывается как расширение Ember.Object
основной командой Ember для удовлетворения этой потребности. Он уже пригоден для использования, но не стабилен, как говорится в документации.
Ember объекты также считаются без схемы . Чтобы ввести значения по умолчанию в объекты Ember, вы расширяете Ember.Object
, передавая объект с таким количеством атрибутов, сколько вам нужно.
1
2
3
4
|
var TaskObject = Ember.Object.extend({
body : «Mow the lawn»
, done : false
});
|
мысли
Backbone имеет консолидированный способ синхронизации с постоянным слоем поверх REST
и это хорошее соглашение. Это еще одна вещь, которую вы должны настроить для работы с внутренним сервером.
Ember работает над тем, чтобы сделать Ember.Data
готовым к использованию, и это выглядит многообещающе. Тем не менее, особенность объектов Ember, имеющих двухстороннюю привязку, упрощает выполнение связей между объектами.
На этом этапе чтения у вас есть точка перегиба между стабильностью Backbone в общении с внутренним сервером и привязками Ember. Все, что для вас важнее, должно определять ваше решение.
Клей — Контроллеры
Это где рамки разойдутся. У них огромный концептуальный пробел в том, как склеивать вещи в вашем приложении. В то время как Backbone стремится оставаться максимально простым и гибким, Ember жертвует размером кодовой базы для лучшей архитектуры. Это компромисс, на самом деле.
Предупреждение: следующие примеры не содержат примеров шаблонов HTML.
позвоночник
Как я уже отмечал, Backbone стремится к простоте, которая преобразуется в гибкость, и он достигает таких атрибутов именно благодаря отсутствию класса контроллера . Большая часть рабочей лошадки распределена по видам, коллекциям, моделям и маршрутизатору (если вы решите использовать Backbone’s Router
).
Учитывая список задач, которыми необходимо управлять, потребуется:
-
Collection
для хранения задач. -
Model
для хранения информации о задаче. -
View
для представления коллекции. - Другое представление для представления каждой задачи.
-
Router
для управления URL.
Большая часть логики приложения будет жить в представлениях, поскольку они соединяют модели с DOM
. Нет четкого разграничения обязанностей, так как мнение делает все. Это может быть полезно для небольших приложений, которые не требуют надежной архитектуры.
Чтобы отобразить список задач, вы должны получить что-то вроде этого:
Коллекция
1
2
3
|
var TaskList = Backbone.Collection.extend({
model : Task
});
|
модель
1
|
var TaskModel = Backbone.Model.extend();
|
Взгляды
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
var TaskListView = Backbone.View.extend({
render: function() {
this.$el.empty();
for (_i = 0, _i < this.collection.length; _i++) {
var task = this.collection.models[_i];
this.$el.append(this.renderItem(task));
}
var tasks = this.$el.html();
this.$el.html(Mustache.to_html(template, {
tasks: tasks,
no_tasks: !this.collection.length
}));
},
renderItem: function(task) {
var view = new Row({ model: task });
var el = view.render();
return el.el;
},
});
|
1
2
3
4
5
6
7
|
var TaskView = Backbone.View.extend({
tagName: «tr»,
render: function() {
this.$el.html(M.to_html(template, this.model.attributes));
return this;
}
});
|
маршрутизатор
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
var Router = Backbone.Router.extend({
initialize: function() {
this.tasks = new TaskList;
this.view = new TaskListView({
collection: this.tasks
});
},
routes: {
«»: «tasks_list»,
},
tasks_list: function() {
this.view.render();
$(«.bucket:first»).html(this.view.el);
},
start: function() {
Backbone.history.start({
pushState: true,
root: «/tickets/»
});
}
});
|
Обратите внимание, что у коллекции нет собственного шаблона; скорее, он делегируется одному представлению задачи, которое отображается и добавляется к конечному результату, помещаемому на страницу.
тлеющие угли
Количество классов, требующих одинаковой настройки, немного больше.
- Вместо
Collection
вас будетArrayController
, который работает очень похоже. - У вас будет дополнительный
ObjectController
для управления одной задачей. - Вместо
Model
вас будетObject
/DS.Model
, который работает одинаково. - Вы бы имели такой же вид.
-
Router
также отвечает за управление URL-адресами.
Вы можете подумать, что эти две структуры не слишком отличаются друг от друга. Это довольно заманчиво, но это не совсем так. Некоторые конкретные различия:
- Контроллер отвечает за взаимодействие с объектами данных, а не с представлением.
- Представления отвечают за обработку
DOM
, а не контроллера. - Представления взаимодействуют с контроллером, а не напрямую с объектами данных.
- Данные, которые подают шаблон представления, на самом деле являются привязкой к данным контроллера.
- Маршрутизатор — это скорее менеджер состояний , который включает в себя гораздо больше, чем просто обработку URL.
Разделение интересов хорошо в долгосрочной перспективе. Контроллер обрабатывает данные, представления обрабатывают DOM
, точку. Этот вид развязанного и связного, бескамерного дизайна позволяет более сфокусированную проверку.
Реализация для отображения одного и того же списка задач будет выглядеть примерно так, учитывая полное приложение Ember:
Корневая архитектура приложения
1
2
3
4
5
6
|
window.App = Ember.Application.create();
App.ApplicationController = Ember.ObjectController.extend();
App.ApplicationView = Ember.View.extend({
templateName: «application»
});
|
объект
1
|
App.Task = Ember.Object.extend();
|
Контроллеры
1
2
3
|
App.TasksController = Ember.ArrayController.extend({
content: []
});
|
Посмотреть
1
2
3
|
App.TasksView = Ember.View.extend({
templateName: «my-list»
});
|
маршрутизатор
1
2
3
4
5
6
7
8
9
|
App.Router = Ember.Router.extend({
root : Ember.Route.extend({
index: Em.Route.extend({
route: ‘/’,
connectOutlets: function(router){
router.get(‘applicationController’).connectOutlet(‘tasks’);
}
})
});
|
В случае с Эмбер мало что говорят о том, как все происходит внутри. Все эти шаблоны убраны, так что вы можете сосредоточиться на том, что действительно имеет значение в вашем приложении: вы определяете объект задачи, контроллер списка задач с массивом, называемым content
, ваше представление и маршрутизатор просто объединяют их все вместе и помещают в стр.
мысли
Понимая, как на самом деле работает Эмбер, она начинает освобождаться.
Как и ожидалось, этот сегмент было труднее всего понять на обеих основах. Backbone было определенно легче изучить, а его гибкий характер позволяет контролировать взаимодействие объектов и DOM
. Это может быть полезно для вас, если вам действительно нужна такая гибкость, но вы все еще хотите поддерживать структуру логики вашего приложения на стороне JavaScript.
Что касается Ember, его захватывающая реализация может поначалу быть пугающей. Однако, осознав, как на самом деле работает Эмбер, она начинает освобождаться. Все соглашения, которые фреймворк устанавливает для вас, освобождают вас от шаблонов и конфигурации, позволяя вам сосредоточиться на своем приложении. Это похоже на то, что Rails сделал для серверной разработки, которая привлекла так много внимания.
Что отличает их?
Ember предназначался для того, чтобы снять общее бремя разработки JavaScript в браузере.
До сих пор весь смысл демонстрации этих двух инструментов состоял в том, чтобы признать их единственную и благородную цель: делегировать власть клиентской стороне как посредством структуры, так и метода .
Основным преимуществом магистрали, безусловно, является подход KISS . Он предоставляет вам минимум возможностей отказаться от DOM
как основного сторонника вашего приложения и начать использовать реальные объекты JavaScript, которые можно протестировать и правильно спроектировать.
Backbone поставляется с коллекциями, моделями, представлениями и роутером, а также другими небольшими утилитами. Вы можете делать с ними все, что пожелаете.
Ember, с другой стороны, был создан с другим мышлением, так как он нацелен на более традиционный и самоуверенный способ создания веб-приложений. Он решает ряд общих проблем, таких как шаблон, привязка данных и шаблоны DOM
поэтому вам не нужно беспокоиться о них с самого начала. Ember предназначался для того, чтобы снять общее бремя разработки JavaScript в браузере .
Ember поставляется с объектами, контроллерами, автоматически обновляемыми представлениями, конечными автоматами, привязками, наблюдателями и маршрутизатором (который также является конечным автоматом), и все это сочетается с хорошей дозой соглашений. У вас есть архитектура, уже спроектированная и готовая начать работать без потери фокуса.
Вывод
Имейте в виду разрыв в обучении. Ваш опыт и культурное наследие будут сильно определять, как быстро вы присоединитесь к клиенту. Если ты боишься, что делать или что выбрать, тогда я ударил тебя по нервам, и это хорошо! Хотите хороший ответ, на котором выбрать? Оба .
Это все о JavaScript
Если вы не уверены, что даже jQuery делает всю свою магию, тогда начните изучать Backbone. Начать проще, а документация очень проста для чтения и понимания. После того, как вы закончите, начните строить что-то. Пачкаться Проверьте эти учебники, если вам нужна помощь.
Если вы все еще в темноте, прочитайте записи Иегуды Каца о том, как работает JavaScript .
Как только вы получите лучшее представление о том, как JavaScript работает как язык, вы начнете лучше понимать, как объекты взаимодействуют друг с другом . Когда вы это сделаете, пойти на Эмбер. Сначала это сложнее, но не сдавайся. Начните читать документы и руководства . Возможно, вы захотите проверить запись в блоге Трека Гловаки, прежде чем запачкать руки.
Мой итог
Лично я склоняюсь к Эмбер; Мне нравится его надежность в макро-масштабе, и я также предпочитаю его соглашения. Backbone — это более гибкий и простой инструмент для небольших приложений или небольших функций внутри существующего приложения.
Я все еще изучаю оба, и у меня есть несколько проблем для решения:
- Автоматические тесты: как их делать и какой набор тестов лучше. Кунит или Жасмин? Безголовый (думая PhantomJS), нод или браузерный тестовый бегун? Пока не уверен.
- Загрузка файлов
- интернационализация
Что ты думаешь обо всем этом разгроме? Есть ли у вас какие-либо проблемы в виду? Какие-либо трудности или препятствия? Дай мне знать!