Комментарии 53
А был ли у вас опыт написание production level проекта на Angular 2? Было бы интересно прочитать про грабли и методы их обхода, если таковые имеются.
Пришел к выводу, что для меня лучше, когда транспиляция идет на клиенте, гораздо удобней отлаживать. Первоначальное отлаживание делаю в хроме, потом перепроверяю всё в IE (в режиме 10 версии, потом в 11 версии).
например вот так не работает в IE10, но работает в 11:
<div [hidden]="!showThisBlock">
содержимое
</div>
Пришлось переделать на *ngIf и покрутить стили, чтобы при показе блок был «правильной» ширины…
[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) — было бы очень полезно и информативно, учитывая ваш подход к ответам на вопросы.
Мне кажется, если и делать это, то в будущем, когда проект выйдет из беты и зарелизится, так как что-то может поменяться. Просто переводить документацию (туториал и быстрый старт) не очень хочется, так как она и так в целом довольно просто написана. Про темы, которые вызывают много вопросов или которые недостаточно описаны в доках, я постараюсь написать. В планах — работа с формами.
Пока же я советую просто читать документацию, а в качестве основы проекта брать вот этот стартер. Там всегда свежие версии фреймворка и хорошие практики в целом. Ну или мой форк этой штуки.
В целом я согласен, велосипедов много. Но в первом.
Во втором же наоборот, от них уходят.
Внедрение зависимостей стало выглядеть как во многих Java/.Net фреймворках. Только тут оно более продвинутое и гибкое.
В проекте используется Rx, который почти на всех языках выглядит одинаково и многим уже известен.
В шаблонах уменьшилось количество специфичных вещей: максимально используются стандартные атрибуты. Например, ng-show/ng-hide исчез, теперь чтобы сделать элемент невидимым используется стандартный атрибут hidden. Тоже самое для событий: вместо ng-click/ng-keypress и т.д. используются стандартные click/keypress.
А вы разницу между импортом и внедрением зависимостей понимаете? Почитайте введение, я же объясняю чем удобно внедрение и почему его используют. Так-то и в Java есть импорты, и что?
Понятно. Статью вы не читали. Потому что я там как раз и рассказал, зачем оно нужно и какие проблемы решает. Пересказывать ещё раз в комментарии я не буду.
Комментарии вы тоже видимо не читаете, так как я уже упоминал, где можно почитать вкратце про DI (например, в этой статье можно).
И вообще, ангулар это фреймворк, а реакт ui-библиотека. Они выполняют разные функции и сравнимы только частично, в области отрисовки ui.
Конечно можно это все реализовать и через сервис-локатор например или просто на коленке, но поддерживать и расширять код с DI имхо намного проще.
С сервис-локатором например 2 варианта использования, либо делать его глобальным, либо прокидывать его через все сущности. При DI инжектор управляет тем, что будет использовать клиентский код, а не клиентский код следит за местоположением сервис-локатора и своими зависимостями (IoC принцип, странно что про него упоминания я не заметил в статье).
А как правильно?
Не развернёте мысль?
Боюсь я не понимаю о чём идёт речь. Сейчас я разрабатываю новый фреймворк и размышляю о механизмах композиции. Пока что наиболее оптимальным мне видится вариант с полностью самодостаточными компонентами, которые сами тянут все зависимости, но любую из них можно перегрузить при создании компонента.
Заумные термины ввели разработчики лет 30 назад. Видимо всё время вы тратите только на изучение того самого "яваскрипт/ES6 функционала", раз не слышали про них и считаете, что это болезненные фантазии.
Паттерны проектирования не ограничены ни фреймворком, ни языками, так что их знание и умение применить всегда будет полезно. Ангуляр лишь реализует некоторые из них.
А как в Angular 2 c производительностью при большом количестве вотчеров? В Angular 1 приходилось использовать библиотеку `bindonce` но и она не везде спасала.
Во втором с производительностью всё отлично. Сам не замерял, но вот, например, есть такой бенчмарк.
Вот более свежая статья. Но там автор плохо умеет писать на втором. Если же всё делать правильно, то скорость возрастает многократно: https://plnkr.co/edit/cjFGtnI704bjSg6F0DEM?p=preview
Ну терминология не относится конкретно к ангуляру, ей уже много лет и она в целом общеизвестна (правда обычно больше в кругах java, .net и c++). Если бы я начал всё расписывать, статья бы растянулась раза в полтора-два… Ссылки постараюсь найти и вставить.
Сервисы и так являются синглтонами, я же писал об этом к конце. Если нужно, чтобы сервис был доступен всем компонентам, регистрировать его надо либо в корневом компоненте, либо в функции bootstrap
.
по незнанию заинжектит зависимость
Не заинжектит, а зарегистрирует в самом компоненте. Если это по-незнанию, то нужно чтобы человек знал, с какими инструментами он работает. Отчасти для этого я и писал статью, так как не все понимают когда и где нужно регистрировать провайдеры. Если, например, в какой-то библиотеке в компоненте регистрируется, например, Http-сервисы, то это косяк библиотеки, а не ангуляра.
Если нужен прям синглтон то… Ну можно сделать просто синглтон. Ещё можно получить родительский инжектор вручную и брать сервисы оттуда.
В текущем проекте на ng1 гора подобных сервисов которые могут быть нужны в разных частях приложения, и офк их нельзя инжектить на уровне всего приложения.
з.ы. за статью спасибо, сходу по оф докам DI был не так прозрачен
Да, это рефлексия. Но рефлексия — фишка конкретно не Typescript, а es7. Typescript лишь обеспечивает простоту использования всего этого. Ангуляр зависит от пакета reflect-metadata, который и делает всю магию.
За рефлексию типов на самом деле, разумеется, отвечает TS. Правда она весьма куцая, работает лишь в тандеме с декораторами и интерфейсы всё же не поддерживает. Похоже вкрутили её по минимуму, чтобы можно было реализовать DI в духе Angular2.
> Это и отличает DI в Angular2 от других DI-фреймворков: в ангуляре у приложения нет одного инжектора, у каждого компонента может быть свой инжектор
Возможно для js мира так но для других языков нет(например http://scaldi.org/).
Angular 2 и внедрение зависимостей