Как стать автором
Обновить

Комментарии 53

Мощно. Спасибо за материал.
А был ли у вас опыт написание production level проекта на Angular 2? Было бы интересно прочитать про грабли и методы их обхода, если таковые имеются.
Мы потихоньку начинаем внедрять… Основная грабля — это IE. Корпоративная политика велит использовать IE, приходится использовать.
Пришел к выводу, что для меня лучше, когда транспиляция идет на клиенте, гораздо удобней отлаживать. Первоначальное отлаживание делаю в хроме, потом перепроверяю всё в IE (в режиме 10 версии, потом в 11 версии).
например вот так не работает в IE10, но работает в 11:
<div [hidden]="!showThisBlock">
   содержимое
</div>

Пришлось переделать на *ngIf и покрутить стили, чтобы при показе блок был «правильной» ширины…
Можно было просто добавить css класс
[hidden] {display:none !important;}
Ну так все правильно — неподдерживаемый атрибут
К тому же полифилится одной строчкой, как заметили ниже, кроме уж совсем извращенных случаев, когда блок с аттрибутом hidden и каким-то классом всё же нужно отобразить. Ангуляр здесь вообще ни при чём.
Кстати "*ngIf" и «display: none» — это не одно и тоже. В случае «display: none» блок не отображается, но он есть и происходит его инициализация, он занимает место в DOM. В случае "*ngIf===false" блока нет и не было.

По работе сейчас пишу 2 проекта на нём. Пока они не сильно большие, но развиваются и растут.
Из граблей:


  • При обновлении с beta.9 до beta.10 были проблемы. Но не у ангуляра, а у одной из зависимости (zone.js). В сети можно было найти пару костылей, как это обойти. Я просто подождал, пока починят и обновился без проблем. На данный момент актуальная версия beta.14. В целом, нужно просто обновляться вручную и не ставить в зависимостях ^.
  • Сейчас не так много библиотек для 2-го ангуляра. Например, Material в стадии альфы, бутстрап-компоненты тоже бывают с багами. Но в целом, нет особых проблем, просто что-то приходится писать руками и я не вижу тут ничего плохого.

Если брать конкретно сам фреймворк, то я сталкивался с такими проблемами:


1) биндинг напрямую к имени класса не работает. Я имею ввиду такую штуку:


<div class="form-group" [class.has-error]="!form.valid"></div>  

Решение:


<div class="form-group" [ngClass]="{ 'has-error': !form.valid }"></div>  

2) Этот баг может всплывать в различных местах, например если мы обрабатываем событие формы submit и в нём переходим на другой адрес. Вот пример, откройте консоль и нажмите на кнопку.
Решение: забить, или делать переход не по событию submit, а, например, через <a> и его click.


3) Не баг, просто ещё не реализованная фича. Иногда некоторые маршруты должны быть с проверкой прав доступа. Во втором ангуляре есть декоратор @CanActivate. Он принимает функцию-коллбек, которая может вернуть либо булевское значение, либо промис. В зависимости от значения результата, роутер либо переходит на нужную локацию, либо нет. Так вот, тут нельзя использовать внедрение зависимостей. А проверку прав или авторизированности пользователя обычно делают в сервисах. Ок, можно самому получить инжектор, передать ему список сервисов и брать нужный сервис оттуда. Но инжектор создаст новые инстансы сервисов. А иногда хочется взять уже готовые и настроенные.
Решение: пока что можно использовать такой хак: сохраняем инстанс корневого компонента или его инжектор в переменной, которая доступна глобально. Когда нужно, берём сервисы из этого инжектора. Вот пример реализации. Вот более объёмный пример с разными кейсами.


Тут дело в том, что авторы просто не решили, как сделать внедрение зависимостей правильно. Просто внедрять зависимости напрямую в декоратор не очень хорошо. Авторы думают и советуются с обществом, как бы это получше сделать. Обсуждение тут или тут.


В общем, ничего критичного нет.

Ваш комментарий содержит полезной информации больше, чем некоторые статьи, и не только на хабре. Спасибо за столь раскрытый ответ.
А вы, часом, не думали написать некоторое подобие туториала? Что-то на подобии React.js для начинающих (статья на habrahabr) — было бы очень полезно и информативно, учитывая ваш подход к ответам на вопросы.

Мне кажется, если и делать это, то в будущем, когда проект выйдет из беты и зарелизится, так как что-то может поменяться. Просто переводить документацию (туториал и быстрый старт) не очень хочется, так как она и так в целом довольно просто написана. Про темы, которые вызывают много вопросов или которые недостаточно описаны в доках, я постараюсь написать. В планах — работа с формами.


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

А теперь обновитесь до RC :)
НЛО прилетело и опубликовало эту надпись здесь

В целом я согласен, велосипедов много. Но в первом.
Во втором же наоборот, от них уходят.


Внедрение зависимостей стало выглядеть как во многих Java/.Net фреймворках. Только тут оно более продвинутое и гибкое.
В проекте используется Rx, который почти на всех языках выглядит одинаково и многим уже известен.
В шаблонах уменьшилось количество специфичных вещей: максимально используются стандартные атрибуты. Например, ng-show/ng-hide исчез, теперь чтобы сделать элемент невидимым используется стандартный атрибут hidden. Тоже самое для событий: вместо ng-click/ng-keypress и т.д. используются стандартные click/keypress.

НЛО прилетело и опубликовало эту надпись здесь

А вы разницу между импортом и внедрением зависимостей понимаете? Почитайте введение, я же объясняю чем удобно внедрение и почему его используют. Так-то и в Java есть импорты, и что?

НЛО прилетело и опубликовало эту надпись здесь

Понятно. Статью вы не читали. Потому что я там как раз и рассказал, зачем оно нужно и какие проблемы решает. Пересказывать ещё раз в комментарии я не буду.
Комментарии вы тоже видимо не читаете, так как я уже упоминал, где можно почитать вкратце про DI (например, в этой статье можно).

НЛО прилетело и опубликовало эту надпись здесь
А какая в реакте может быть работа с зависимостями? из коробки никакой.
И вообще, ангулар это фреймворк, а реакт ui-библиотека. Они выполняют разные функции и сравнимы только частично, в области отрисовки ui.
НЛО прилетело и опубликовало эту надпись здесь
У нас большой проект на реакте и мы юзаем DI (очень похожую на DI angular2), это дает возможность удобно использовать модульность. Например можно объявить интерфейс модуля и уже в рантайме биндить к интерфейсу модуля конкретную реализацию. при этом сами модули ничего не знают друг о друге, только об интерфейсах.

Конечно можно это все реализовать и через сервис-локатор например или просто на коленке, но поддерживать и расширять код с DI имхо намного проще.

С сервис-локатором например 2 варианта использования, либо делать его глобальным, либо прокидывать его через все сущности. При DI инжектор управляет тем, что будет использовать клиентский код, а не клиентский код следит за местоположением сервис-локатора и своими зависимостями (IoC принцип, странно что про него упоминания я не заметил в статье).
НЛО прилетело и опубликовало эту надпись здесь

А как правильно?

НЛО прилетело и опубликовало эту надпись здесь

Не развернёте мысль?

НЛО прилетело и опубликовало эту надпись здесь

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

НЛО прилетело и опубликовало эту надпись здесь

Что такое "пересборка иерархии"?

НЛО прилетело и опубликовало эту надпись здесь

А зачем?

НЛО прилетело и опубликовало эту надпись здесь

И чем тут может помочь "пересборка массивов"? Может приведёте пример кода?

НЛО прилетело и опубликовало эту надпись здесь

Заумные термины ввели разработчики лет 30 назад. Видимо всё время вы тратите только на изучение того самого "яваскрипт/ES6 функционала", раз не слышали про них и считаете, что это болезненные фантазии.
Паттерны проектирования не ограничены ни фреймворком, ни языками, так что их знание и умение применить всегда будет полезно. Ангуляр лишь реализует некоторые из них.

Вы что-то путаете. Внедрение зависимостей совсем не то же самое что require/import.
Отличная статья, спасибо!
Тот самый момент, когда хочется переписать заново недавно законченый огромный проект на Angular 1.
А как в Angular 2 c производительностью при большом количестве вотчеров? В Angular 1 приходилось использовать библиотеку `bindonce` но и она не везде спасала.
Да, спасибо, прочел. Нашел в статье упоминание про `new the change detection machanism`, что привело меня к другой статье о механизме распознавания изменений, которая оказалась еще более интересной.
Как человеку, не очень знакомому с экосистемой Angular, мне не хватило какого-то введения, хотя бы в терминологию с пояснениями. Можно было просто ссылочки дать. Причём, я не могу сказать, что ничего про Angular 2 не знаю. Многое читал и многое мне было понятно… Но сейчас вроде статью прочитал, вроде даже что-то понял, в голове всё равно, в основном звенят только «Инжектор», «Провайдер», «Сервис», «Фабрика»…

Ну терминология не относится конкретно к ангуляру, ей уже много лет и она в целом общеизвестна (правда обычно больше в кругах java, .net и c++). Если бы я начал всё расписывать, статья бы растянулась раза в полтора-два… Ссылки постараюсь найти и вставить.

Вот оно что :) У меня, к сожеланию, нет общения с java, .net и c++, привык вращаться в среде жаваскрипта и эти штуки, пока, выглядят экзотично и кажутся слегка избыточными ) Хотя в целом Agunlar2 нравится. Смущает пока только размер пакета.
«Для более лучшего понимания» это как «более лучше одеваться»?
Не подскажете, как зарегестрировать сервис как синглтон во втором ангуляре?

Сервисы и так являются синглтонами, я же писал об этом к конце. Если нужно, чтобы сервис был доступен всем компонентам, регистрировать его надо либо в корневом компоненте, либо в функции bootstrap.

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

Не заинжектит, а зарегистрирует в самом компоненте. Если это по-незнанию, то нужно чтобы человек знал, с какими инструментами он работает. Отчасти для этого я и писал статью, так как не все понимают когда и где нужно регистрировать провайдеры. Если, например, в какой-то библиотеке в компоненте регистрируется, например, Http-сервисы, то это косяк библиотеки, а не ангуляра.


Если нужен прям синглтон то… Ну можно сделать просто синглтон. Ещё можно получить родительский инжектор вручную и брать сервисы оттуда.

Допустим в проекте есть сервис с данными пользователя(залогинен/гость и всякое разное) User. Проект разбит на независимые модули(например разделы сайта/функционала) и в разных модулях нам нужны данные пользователя. Логично что инжектить User на уровне приложения как-то не очень, тем более есть множество других случаев с более редкими сервисами используемыми в разных частях приложения(в разных модулях), поэтому мы его(их) инжектим внутри каждого отдельного модуля или уже конкретно на месте, в компоненте. И тут сталкиваемся с тем, что для каждого модуля(компонента) у нас будет свой инстанс этого сервиса, а нужен один общий синглтон, инициализированный единственный раз. Как быть?
В текущем проекте на ng1 гора подобных сервисов которые могут быть нужны в разных частях приложения, и офк их нельзя инжектить на уровне всего приложения.

з.ы. за статью спасибо, сходу по оф докам DI был не так прозрачен
Пока читал Ваш комментарий, пришла такая мысль: что если реализовать синглтон на уровне фабрики? Ну, то есть, инжектим везде через { useFactory:… }, а в фабрике соответственно, не создаем каждый раз новый объект, а возвращаем однажды созданный. А чтобы никто не внедрил сервис в обход фабрики сделать проверку уже в рантайме, определив каким-то образом, откуда вызыван конструктор сервиса — из фабрики или как-то еще (например, опциональный параметр).
В одном из первых примеров у сервиса UserService определена зависимость от Logger (в конструкторе _logger: Logger). Однако при компиляции тайпскрипта в яваскрипт тип аргумента потеряется. Откуда ангуляр знает что первый аргумент в конструкторе UserService это зависимость именно типа Logger? В тайпскрипте есть рефлексия/метаданные?

Да, это рефлексия. Но рефлексия — фишка конкретно не Typescript, а es7. Typescript лишь обеспечивает простоту использования всего этого. Ангуляр зависит от пакета reflect-metadata, который и делает всю магию.

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

За рефлексию типов на самом деле, разумеется, отвечает TS. Правда она весьма куцая, работает лишь в тандеме с декораторами и интерфейсы всё же не поддерживает. Похоже вкрутили её по минимуму, чтобы можно было реализовать DI в духе Angular2.

Прикольно, зашел почитать про js, а читаешь про родную Java.

> Это и отличает DI в Angular2 от других DI-фреймворков: в ангуляре у приложения нет одного инжектора, у каждого компонента может быть свой инжектор
Возможно для js мира так но для других языков нет(например http://scaldi.org/).
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации