AngularJS против JQuery
AngularJS и jQuery используют совершенно разные идеологии. Если вы пришли из jQuery, вы можете найти некоторые различия удивительными. Angular может разозлить вас.
Это нормально, вы должны протолкнуться. Angular того стоит.
Большая разница (TLDR)
jQuery предоставляет вам инструментарий для выбора произвольных битов DOM и внесения в них специальных изменений. Вы можете делать практически все, что вам нравится по частям.
AngularJS вместо этого дает вам компилятор .
Это означает, что AngularJS читает весь DOM сверху вниз и обрабатывает его как код, буквально как инструкции для компилятора. Обходя DOM, он ищет конкретные директивы ( директивы компилятора), которые сообщают компилятору AngularJS, как себя вести и что делать. Директивы - это маленькие объекты, полные JavaScript, которые могут сопоставляться с атрибутами, тегами, классами или даже комментариями.
Когда компилятор Angular определяет, что часть DOM соответствует определенной директиве, он вызывает функцию директивы, передавая ей элемент DOM, любые атрибуты, текущий $ scope (который является хранилищем локальной переменной) и некоторые другие полезные биты. Эти атрибуты могут содержать выражения, которые могут быть интерпретированы Директивой и которые сообщают ей, как визуализировать и когда он должен сам перерисовываться.
Директивы могут, в свою очередь, включать дополнительные компоненты Angular, такие как контроллеры, сервисы и т. Д. В нижней части компилятора находится полностью сформированное веб-приложение, подключенное и готовое к работе.
Это означает, что Angular управляется на основе шаблонов . Ваш шаблон управляет JavaScript, а не наоборот. Это радикальное изменение ролей и полная противоположность ненавязчивому JavaScript, который мы пишем последние 10 лет или около того. Это может занять некоторое привыкание.
Если это звучит так, как будто это слишком предписывает и ограничивает, ничто не может быть дальше от истины. Поскольку AngularJS рассматривает ваш HTML как код, вы получаете гранулярность уровня HTML в своем веб-приложении . Все возможно, и большинство вещей на удивление легко, когда вы делаете несколько концептуальных скачков.
Давай перейдем к мельчайшим пескам.
Во-первых, Angular не заменяет jQuery
Angular и JQuery делают разные вещи. AngularJS предоставляет вам набор инструментов для создания веб-приложений. В основном jQuery предоставляет инструменты для изменения DOM. Если jQuery присутствует на вашей странице, AngularJS будет использовать его автоматически. Если это не так, AngularJS поставляется с jQuery Lite, который является урезанной, но все еще отлично используемой версией jQuery.
Миско любит jQuery и не возражает против того, чтобы вы его использовали. Однако по мере продвижения вы обнаружите, что вы можете выполнить почти всю свою работу, используя комбинацию области действия, шаблонов и директив, и вам следует предпочесть этот рабочий процесс, где это возможно, потому что ваш код будет более дискретным, более настраиваемым и более Угловой.
Если вы используете jQuery, вы не должны разбрасывать его повсюду. Правильное место для манипулирования DOM в AngularJS находится в директиве. Подробнее об этом позже.
Ненавязчивый JavaScript с селекторами и декларативными шаблонами
jQuery обычно применяется незаметно. Ваш код JavaScript связан в верхнем или нижнем колонтитуле, и это единственное место, где он упоминается. Мы используем селекторы, чтобы выбрать биты страницы и написать плагины для изменения этих частей.
JavaScript находится под контролем. HTML имеет полностью независимое существование. Ваш HTML остается семантическим даже без JavaScript. Атрибуты Onclick - очень плохая практика.
Первое, что вы заметите в AngularJS, это то, что пользовательские атрибуты есть везде . Ваш HTML будет завален атрибутами ng, которые по сути являются атрибутами onClick на стероидах. Это директивы (директивы компилятора), и они являются одним из основных способов привязки шаблона к модели.
Когда вы впервые увидите это, у вас может возникнуть искушение списать AngularJS как навязчивый JavaScript старой школы (как я делал вначале). На самом деле AngularJS не играет по этим правилам. В AngularJS ваш HTML5 является шаблоном. Он скомпилирован AngularJS для создания вашей веб-страницы.
Это первая большая разница. Для jQuery ваша веб-страница - это DOM, которым нужно манипулировать. Для AngularJS ваш HTML - это код для компиляции. AngularJS читает всю вашу веб-страницу и буквально компилирует ее в новую веб-страницу, используя встроенный компилятор.
Ваш шаблон должен быть декларативным; его значение должно быть ясно, просто прочитав его. Мы используем пользовательские атрибуты со значимыми именами. Мы создаем новые элементы HTML, опять же со значимыми именами. Дизайнер с минимальными знаниями HTML и навыками программирования не может прочитать ваш шаблон AngularJS и понять, что он делает. Он или она может вносить изменения. Это угловой путь.
Шаблон находится в водительском кресле.
Один из первых вопросов, которые я задавал себе при запуске AngularJS и прохождении руководств, - «Где мой код?» , Я не написал JavaScript, и все же у меня есть все это поведение. Ответ очевиден. Поскольку AngularJS компилирует DOM, AngularJS рассматривает ваш HTML как код. Для многих простых случаев часто достаточно просто написать шаблон и позволить AngularJS скомпилировать его в приложение для вас.
Ваш шаблон управляет вашим приложением. Это рассматривается как DSL . Вы пишете компоненты AngularJS, а AngularJS позаботится о том, чтобы вытянуть их и сделать их доступными в нужное время в зависимости от структуры вашего шаблона. Это сильно отличается от стандартного шаблона MVC , где шаблон предназначен только для вывода.
Например, он больше похож на XSLT, чем на Ruby on Rails .
Это радикальная инверсия контроля, к которой нужно привыкнуть.
Прекратите пытаться вытеснить ваше приложение из вашего JavaScript. Пусть шаблон управляет приложением, а AngularJS позаботится о соединении компонентов. Это и есть угловой путь.
Семантический HTML против семантических моделей
С помощью jQuery ваша HTML-страница должна содержать смысловой контент. Если JavaScript отключен (пользователем или поисковой системой), ваш контент остается доступным.
Потому что AngularJS рассматривает вашу HTML-страницу как шаблон. Шаблон не должен быть семантическим, так как ваш контент обычно хранится в вашей модели, которая в конечном итоге исходит из вашего API. AngularJS компилирует ваш DOM с моделью для создания семантической веб-страницы.
Ваш HTML-источник больше не является семантическим, вместо этого ваш API и скомпилированный DOM являются семантическими.
В AngularJS, что означает жизнь в модели, HTML - это просто шаблон, только для отображения.
На данный момент у вас, вероятно, есть все виды вопросов, касающихся SEO и доступности, и это правильно. Здесь есть открытые вопросы. Большинство программ чтения с экрана теперь будут анализировать JavaScript. Поисковые системы также могут индексировать контент AJAX . Тем не менее, вы захотите убедиться, что вы используете URL-адреса pushstate и у вас есть приличная карта сайта. Смотрите здесь для обсуждения проблемы: https://stackoverflow.com/a/23245379/687677
Разделение интересов (SOC) против MVC
Разделение интересов (SOC) - это модель, которая выросла за многие годы веб-разработки по ряду причин, включая SEO, доступность и несовместимость браузера. Это выглядит так:
- HTML - семантическое значение. HTML должен стоять отдельно.
- CSS - стилизация, без CSS страница по-прежнему читаема.
- JavaScript - поведение, без скрипта контент остается.
Опять же AngularJS не играет по своим правилам. Одним словом , AngularJS избавляется от десятилетия полученной мудрости и вместо этого реализует шаблон MVC, в котором шаблон больше не является семантическим, даже немного.
Это выглядит так:
- Модель - ваши модели содержат ваши семантические данные. Модели обычно являются объектами JSON . Модели существуют как атрибуты объекта с именем $ scope. Вы также можете хранить полезные служебные функции в $ scope, к которым ваши шаблоны смогут получить доступ.
- Вид - Ваши взгляды написаны в HTML. Представление обычно не семантическое, потому что ваши данные живут в модели.
- Контроллер - ваш контроллер представляет собой функцию JavaScript, которая привязывает представление к модели. Его функция заключается в инициализации $ scope. В зависимости от вашего приложения вам может понадобиться или не потребоваться создание контроллера. Вы можете иметь много контроллеров на странице.
MVC и SOC не находятся на противоположных концах одной и той же шкалы, они находятся на совершенно разных осях. SOC не имеет смысла в контексте AngularJS. Вы должны забыть это и двигаться дальше.
Если, как и я, вы пережили войны браузеров, вы могли бы найти эту идею довольно оскорбительной. Преодолей это, оно того стоит, я обещаю.
Плагины против Директив
Плагины расширяют jQuery. Директивы AngularJS расширяют возможности вашего браузера.
В jQuery мы определяем плагины, добавляя функции в jQuery.prototype. Затем мы подключаем их к DOM, выбирая элементы и вызывая плагин для результата. Идея состоит в том, чтобы расширить возможности jQuery.
Например, если вам нужна карусель на вашей странице, вы можете определить неупорядоченный список фигур, возможно, обернутый в элемент nav. Затем вы можете написать jQuery для выбора списка на странице и изменить его стиль как галерею с тайм-аутами для выполнения скользящей анимации.
В AngularJS мы определяем директивы. Директива - это функция, которая возвращает объект JSON. Этот объект сообщает AngularJS, какие элементы DOM искать и какие изменения в них вносить. Директивы подключаются к шаблону с помощью атрибутов или элементов, которые вы придумываете. Идея состоит в том, чтобы расширить возможности HTML с помощью новых атрибутов и элементов.
Способ AngularJS - расширить возможности нативно выглядящего HTML. Вы должны написать HTML, который выглядит как HTML, расширенный с помощью пользовательских атрибутов и элементов.
Если вы хотите использовать карусель, просто используйте <carousel />
элемент, затем определите директиву для извлечения шаблона и заставьте эту присоску работать.
Множество маленьких директив против больших плагинов с конфигурационными переключателями
Тенденция в jQuery - писать большие большие плагины, такие как лайтбокс, которые мы затем настраиваем, передавая множество значений и опций.
Это ошибка в AngularJS.
Возьмите пример выпадающего списка. При написании выпадающего плагина у вас может возникнуть желание написать код в обработчиках кликов, возможно, добавить функцию в шеврон или вверх или вниз, изменить класс развернутого элемента, показать скрыть меню, все полезные вещи.
Пока вы не хотите внести небольшие изменения.
Скажем, у вас есть меню, которое вы хотите развернуть при наведении курсора. Ну, теперь у нас есть проблема. Наш плагин встроен в наш обработчик кликов, нам нужно добавить опцию конфигурации, чтобы в этом конкретном случае он вел себя по-другому.
В AngularJS мы пишем меньшие директивы. Наша выпадающая директива была бы смехотворно мала. Он может поддерживать сложенное состояние и предоставлять методы для fold (), unfold () или toggle (). Эти методы просто обновят $ scope.menu.visible, который является логическим значением, содержащим состояние.
Теперь в нашем шаблоне мы можем подключить это:
<a ng-click="toggle()">Menu</a>
<ul ng-show="menu.visible">
...
</ul>
Нужно обновить при наведении курсора?
<a ng-mouseenter="unfold()" ng-mouseleave="fold()">Menu</a>
<ul ng-show="menu.visible">
...
</ul>
Шаблон управляет приложением, поэтому мы получаем уровень детализации HTML. Если мы хотим сделать исключения для каждого конкретного случая, шаблон делает это легко.
Закрытие против $ scope
Плагины JQuery создаются в замыкании. Конфиденциальность сохраняется в течение этого закрытия. Вы должны поддерживать свою цепочку прицелов в этом закрытии. У вас действительно есть доступ только к набору узлов DOM, переданных плагину с помощью jQuery, а также к любым локальным переменным, определенным в замыкании, и любым глобальным переменным, которые вы определили. Это означает, что плагины совершенно автономны. Это хорошо, но может стать ограничением при создании всего приложения. Попытка передать данные между разделами динамической страницы становится рутиной.
AngularJS имеет объекты $ scope. Это специальные объекты, созданные и поддерживаемые AngularJS, в которых вы храните свою модель. Некоторые директивы будут порождать новую область $ scope, которая по умолчанию наследует от своей оболочки $ scope, используя прототипическое наследование JavaScript. Объект $ scope доступен в контроллере и представлении.
Это умная часть. Поскольку структура наследования $ scope примерно соответствует структуре DOM, элементы имеют доступ к своей собственной области, и любые содержащие области видимости плавно, вплоть до глобальной области $ (которая не совпадает с глобальной областью действия).
Это значительно упрощает передачу данных и хранение данных на соответствующем уровне. Если раскрывающийся список развернут, об этом должна знать только раскрывающаяся область $. Если пользователь обновляет свои предпочтения, вы можете обновить глобальную область $, и любые вложенные области, прослушивающие предпочтения пользователя, будут автоматически предупреждены.
Это может показаться сложным, на самом деле, когда вы расслабляетесь, это похоже на полет. Вам не нужно создавать объект $ scope, AngularJS создает и настраивает его для вас правильно и в соответствии с иерархией вашего шаблона. Затем AngularJS делает его доступным для вашего компонента, используя магию внедрения зависимостей (подробнее об этом позже).
Изменения DOM вручную против привязки данных
В jQuery вы вносите все изменения DOM вручную. Вы создаете новые элементы DOM программно. Если у вас есть массив JSON и вы хотите поместить его в DOM, вы должны написать функцию для генерации HTML и вставки его.
В AngularJS вы тоже можете это сделать, но вам рекомендуется использовать привязку данных. Измените вашу модель, и, поскольку DOM привязан к ней через шаблон, ваш DOM будет автоматически обновляться, никакого вмешательства не требуется.
Поскольку привязка данных выполняется из шаблона с использованием атрибута или синтаксиса фигурных скобок, это сделать очень просто. С этим связаны небольшие когнитивные издержки, поэтому вы обнаружите, что делаете это все время.
<input ng-model="user.name" />
Привязывает элемент ввода к $scope.user.name
. Обновление входных данных приведет к обновлению значения в текущей области, и наоборот.
Точно так же:
<p>
{{user.name}}
</p>
выведет имя пользователя в абзаце. Это живая привязка, поэтому, если $scope.user.name
значение будет обновлено, шаблон тоже обновится.
Аякс все время
В jQuery сделать Ajax-вызов довольно просто, но вы все равно можете подумать дважды. Есть дополнительная сложность для размышления и большой кусок сценария для обслуживания.
В AngularJS Ajax - это стандартное решение по умолчанию, и это происходит постоянно, почти без вашего ведома. Вы можете включать шаблоны с помощью ng-include. Вы можете применить шаблон с простейшей пользовательской директивой. Вы можете заключить вызов Ajax в службу и создать себе службу GitHub или службу Flickr , к которой вы можете обращаться с удивительной легкостью.
Сервисные объекты и вспомогательные функции
В jQuery, если мы хотим выполнить небольшую не связанную с dom задачу, такую как получение канала из API, мы могли бы написать небольшую функцию для этого в нашем закрытии. Это правильное решение, но что, если мы хотим часто получать доступ к этому каналу? Что если мы хотим повторно использовать этот код в другом приложении?
AngularJS предоставляет нам объекты обслуживания.
Сервисы - это простые объекты, которые содержат функции и данные. Они всегда одиночные, то есть никогда не может быть больше одного из них. Скажем, мы хотим получить доступ к API переполнения стека, мы могли бы написать, StackOverflowService
который определяет методы для этого.
Допустим, у нас есть корзина для покупок. Мы можем определить ShoppingCartService, который поддерживает нашу корзину и содержит методы для добавления и удаления товаров. Поскольку служба является одноэлементной и используется всеми другими компонентами, любой объект, который должен быть записан в корзину и извлекает из него данные. Это всегда одна и та же тележка.
Сервисные объекты - это автономные компоненты AngularJS, которые мы можем использовать и использовать по своему усмотрению. Это простые объекты JSON, содержащие функции и данные. Они всегда единичны, поэтому, если вы храните данные в службе в одном месте, вы можете получить эти данные в другом месте, просто запросив ту же услугу.
AngularJS управляет вашими зависимостями для вас. Если вам нужен объект, просто обратитесь к нему, и AngularJS получит его для вас.
До тех пор, пока вы не начнете использовать это, трудно объяснить, что это за огромное время. Ничего подобного AngularJS DI не существует внутри jQuery.
DI означает, что вместо того, чтобы писать свое приложение и связывать его вместе, вы определяете библиотеку компонентов, каждый из которых идентифицируется строкой.
Скажем, у меня есть компонент под названием «FlickrService», который определяет методы для получения потоков JSON из Flickr. Теперь, если я хочу написать контроллер, который может обращаться к Flickr, мне просто нужно обратиться к «FlickrService» по имени, когда я объявляю контроллер. AngularJS позаботится о том, чтобы создать экземпляр компонента и сделать его доступным для моего контроллера.
Например, здесь я определяю сервис:
myApp.service('FlickrService', function() {
return {
getFeed: function() { // do something here }
}
});
Теперь, когда я хочу использовать этот сервис, я просто называю его по имени так:
myApp.controller('myController', ['FlickrService', function(FlickrService) {
FlickrService.getFeed()
}]);
AngularJS распознает, что объект FlickrService необходим для создания экземпляра контроллера, и предоставит его нам.
Это делает соединение вещей очень простым и в значительной степени устраняет любую тенденцию к спагеттификации. У нас есть полный список компонентов, и AngularJS передает их нам один за другим, как и когда они нам нужны.
Модульная сервисная архитектура
JQuery очень мало говорит о том, как вы должны организовать свой код. AngularJS имеет мнения.
AngularJS предоставляет вам модули, в которые вы можете поместить свой код. Если вы пишете сценарий, который взаимодействует, например, с Flickr, вы можете создать модуль Flickr, чтобы обернуть в него все функции, связанные с Flickr. Модули могут включать другие модули (DI). Ваше основное приложение обычно является модулем, и оно должно включать все другие модули, от которых будет зависеть ваше приложение.
Вы получаете простое повторное использование кода, если вы хотите написать другое приложение на основе Flickr, вы можете просто включить модуль Flickr и вуаля, у вас есть доступ ко всем функциям, связанным с Flickr, в вашем новом приложении.
Модули содержат компоненты AngularJS. Когда мы включаем модуль, все компоненты в этом модуле становятся доступны нам в виде простого списка, идентифицируемого их уникальными строками . Затем мы можем внедрить эти компоненты друг в друга, используя механизм внедрения зависимостей AngularJS.
Подводить итоги
AngularJS и jQuery не являются врагами. В AngularJS можно очень хорошо использовать jQuery. Если вы хорошо используете AngularJS (шаблоны, привязка данных, $ scope, директивы и т. Д.), Вы обнаружите, что вам нужно намного меньше jQuery, чем в противном случае.
Главное понять, что ваш шаблон управляет вашим приложением. Перестаньте пытаться писать большие плагины, которые делают все. Вместо этого напишите маленькие директивы, которые делают одно, а затем напишите простой шаблон, чтобы связать их вместе.
Думайте меньше о ненавязчивом JavaScript, и вместо этого думайте с точки зрения расширений HTML.
Моя маленькая книга
Я так взволнован AngularJS, я написал небольшую книгу, которую вы можете прочитать онлайн http://nicholasjohnson.com/angular-book/ . Я надеюсь, что это полезно.