Pull to refresh

Comments 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 :)
UFO just landed and posted this here

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


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

UFO just landed and posted this here

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

UFO just landed and posted this here

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

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

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

С сервис-локатором например 2 варианта использования, либо делать его глобальным, либо прокидывать его через все сущности. При DI инжектор управляет тем, что будет использовать клиентский код, а не клиентский код следит за местоположением сервис-локатора и своими зависимостями (IoC принцип, странно что про него упоминания я не заметил в статье).
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here

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

UFO just landed and posted this here

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

UFO just landed and posted this here
UFO just landed and posted this here

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

UFO just landed and posted this here

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

Вы что-то путаете. Внедрение зависимостей совсем не то же самое что require/import.
Тот самый момент, когда хочется переписать заново недавно законченый огромный проект на Angular 1.
А как в Angular 2 c производительностью при большом количестве вотчеров? В Angular 1 приходилось использовать библиотеку `bindonce` но и она не везде спасала.
Как человеку, не очень знакомому с экосистемой 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/).
Sign up to leave a comment.

Articles