AngularJS хитрости
AngularJS МОЖЕТ быть увлекательным!
AngularJS МОЖЕТ БЫТЬ УВЛЕКАТЕЛЬНЫМ!
Для: AngularJS v1.x
- Разработчики AngularJS быстро обнаруживают, что их средние и крупные приложения под давлением рассыпаются из-за разбросанных
$watchи часто громоздкой опоры под названием$scope. - Сохраняйте
$scopeв чистоте от избыточного состояния UI, постарайтесь ограничить размер & глубину вашей общей иерархии.
Двустороннее связывание данных: двусторонний меч
Двустороннее связывание само по себе делает переход из других фреймворков вроде Backbone просто потрясающим.
Проблема в том, что многие сайты хронически переиспользуют паттерны проектирования Angular.
Это приводит к распространению директив и $scope/rootScope, которые легко могут содержать тысячи экземпляров и цепляться к огромным объектам, препятствуя эффективной сборке мусора.
Вы уже понимаете, к чему это приведет: браузер, истощенный работой! Навсегда приговоренный работать с бешеной скоростью, выполняя бесконечные и избыточные перекомпиляции UI/DOM.
Стоп! Перестаньте злоупотреблять Angular.JS
«Если у вас в руках только молоток, то все проблемы начинают выглядеть как гвозди»
— старая поговорка
Есть ли у вашей программы проблемы с директивами?
current-user-status-label div(ng-if='loggedIn') view-user-surplusage(ng-if='!editMode') .head: contact-details(user='user') .tool: contact-buttons(loggedIn='loggedIn') a.edit-icon(ng-click='editMode = true') edit-user-surplusage(ng-if='editMode') .head: avatar-edit(user='user') .body: edit-contact-details(user='user') a.save-icon(ng-click='editMode = false')Давайте спроектируем гибкий пользовательский виджет, который поможет:
- Гибкая компонентизация с DRY-кодом Angular
- Понятные директивы с минимальной глубиной вложенности (обратите внимание на
ng-repeats) - Простой сервисный слой
- Минимальное количество фактического кода для реализации — только HTML/код представления
// jadeuser-widget div(ng-if='loggedIn') div.edit(ng-if='editMode') h4.email-icon: input(type='email', ng-model='user.email') h4.phone-icon: input(type='email', ng-model='user.phone') a.save-icon(ng-click='editMode = false') div.show(ng-if='!editMode') h1.users-icon {{ user.name }} h4.email-icon {{ user.email }} h4.phone-icon {{ user.phone }} a.edit-icon(ng-click='editMode = true') div(ng-if='!loggedIn') h5: i Welcome User a.btn(href='/login') LoginРешения
Советы по Angular
- Используйте одностороннее связывание (например,
{ :: title }) - Ограничьте рекурсивное вложение директив
- И если вы всё же должны вкладывать директивы, НИКОГДА не делайте это внутри
ng-repeat- Производительность начнёт напоминать что-то вродеO(n^2)^3;) I. Используйте нативный JS/DOM код в паттерне фабрики для создания базовых DOM/UI фрагментов, примеры: Всплывающее сообщение, статусная строка. Вызывайте фабрики UI из директив или контроллеров. - Бонус: Понимайте стоимость и триггеры браузерного рендер-цикла: анимация, композитный рендеринг, рефлоу
Используйте Browserify для организации проекта
Не специально для Angular, но важен для простого разрешения зависимостей.
Browserify делает JS-проекты управляемыми с минимальной накладной стоимостью (около нескольких сотен символов).
Просто прочитайте этот раздел руководства по Browserify.
Альтернативы
ReactJS от Facebook
Если у вас много мелких переиспользуемых компонентов UI — ReactJS может быть лучшим выбором:
- Если ваш проект…?:
- Имеет другую философию реализации UI/DOM, чем Angular
- Уже имеет какой-то вид “фреймворка” — Вы можете использовать ReactJS параллельно с AngularJS, Ember, Backbone. (Постарайтесь избегать, если возможно).
- Обрабатывает частые изменения модели данных в своем коде, вы избавитесь от хаотичного характера паттерна digest/loop в Angular
Polymer Project от Google
Чистый JS подход
- Кстати, вот как я пытаюсь создавать код, независимый от фреймворка (+1 тестируемость, +1 переиспользование)
- Используйте обычный класс JavaScript для загрузки данных (AJAX/JSONP/Встроенные в страницу и т.д.)
- Используйте шаблонизацию Mustache для создания строк HTML (или DOM напрямую)
- Кэшируйте отрендеренный контент в localStorage, если возможно
- (Опционально) Теперь добавьте обработчик событий для повторного рендера содержимого. Я стандартизировал имя события как
refresh.<class-name>