В чем разница между этими двумя и каковы варианты использования каждого из них?
Эти документы не совсем полезны:
forRoot создает модуль, содержащий все директивы, указанные маршруты и сам сервис маршрутизатора.
forChild создает модуль, содержащий все директивы и заданные маршруты, но не включающий службу маршрутизатора.
Я смутно предполагаю, что один предназначен для «основного» модуля, а другой - для любых импортированных модулей (поскольку они уже будут иметь службу, доступную из основного модуля), но я действительно не могу придумать вариант использования.
RouterService
для одного приложения Angular2.forRoot
инициализирует эту услугу и зарегистрировать его в DI вместе с какой - то маршрут конфигурации, в то время какforChild
только зарегистрировать дополнительные конфиги маршрут и сказать Angular2 , чтобы повторно использовать ,RouterService
чтоforRoot
создал.Ответы:
Я настоятельно рекомендую прочитать эту статью:
Модуль с провайдерами
Когда вы импортируете модуль, вы обычно используете ссылку на класс модуля:
Таким образом, все провайдеры, зарегистрированные в модуле,
A
будут добавлены в корневой инжектор и будут доступны для всего приложения.Но есть еще один способ зарегистрировать модуль у таких провайдеров:
Это имеет те же последствия, что и предыдущее.
Вы, наверное, знаете, что у ленивых модулей есть собственный инжектор. Итак, предположим, вы хотите зарегистрироваться,
AService
чтобы они были доступны для всего приложения, а некоторые из нихBService
были доступны только для ленивых модулей. Вы можете реорганизовать свой модуль следующим образом:Теперь
BService
будет доступен только для дочерних ленивых модулей иAService
будет доступен для всего приложения.Вы можете переписать это как экспортированный модуль следующим образом:
Как это относится к RouterModule?
Предположим, они оба доступны с использованием одного и того же токена:
С отдельными конфигурациями, когда вы запрашиваете
token
из ленивого загружаемого модуля, вы получаете то,BService
что планировалось.RouterModule использует
ROUTES
токен для получения всех маршрутов, специфичных для модуля. Поскольку он хочет, чтобы маршруты, относящиеся к ленивому загружаемому модулю, были доступны внутри этого модуля (аналог нашего BService), он использует другую конфигурацию для лениво загружаемых дочерних модулей:источник
forRoot
модуля с отложенной загрузкой создаст новые экземпляры всех глобальных служб в инжекторе модуля с отложенной загрузкой. Да, это приведет к непредсказуемым результатам. Также прочтите эту статью Как избежать общей путаницы с модулями в AngularЯ думаю, что ответы верны, но я думаю, что чего-то не хватает.
Не хватает того, «почему и что это решает?».
Хорошо, давайте начнем.
Сначала упомянем некоторую информацию:
Все модули имеют доступ к корневым службам.
Таким образом, даже ленивые модули могут использовать службу, которая была предоставлена в
app.module
.Что произойдет, если ленивый загруженный модуль предоставит себе услугу, которую уже предоставил модуль приложения? будет 2 экземпляра.
Это не проблема, но иногда бывает .
Как мы можем это решить? просто не импортируйте модуль с этим поставщиком в модули с отложенной загрузкой.
Конец истории.
Это ^ было просто для того, чтобы показать, что модули с ленивой загрузкой имеют свою собственную точку внедрения (в отличие от модулей с ленивой загрузкой).
Но что произойдет, если объявлен разделяемый (!) Модуль
providers
, и этот модуль будет импортирован ленивым иapp.module
? Опять же, как мы уже сказали, два случая.Итак, как мы можем решить эту проблему в общем модуле POV? Нам нужен способ не использовать
providers:[]
! Зачем? потому что они будут автоматически импортированы как в ленивый, так и в app.module, и мы этого не хотим, поскольку мы видели, что у каждого будет свой экземпляр.Что ж, получается, что мы можем объявить общий модуль, который не будет иметь
providers:[]
, но все же предоставит провайдеров (извините :))Как? Как это :
Заметьте, нет провайдеров.
Но
что будет теперь, когда app.module импортирует общий модуль с POV сервиса? НИЧЕГО.
что будет теперь, когда ленивый модуль импортирует общий модуль с POV службы? НИЧЕГО.
Ввод ручного механизма через соглашение:
Вы заметите, что у провайдеров на картинках есть
service1
иservice2
Это позволяет нам импортировать
service2
как ленивые, так иservice1
неленивые модули. ( кашель ... роутер .... кашель )Кстати, никто не мешает вам звонить
forRoot
в ленивом модуле. но у вас будет 2 экземпляра, потомуapp.module
что это тоже должно быть - так что не делайте этого в ленивых модулях.Также - если
app.module
звонитforRoot
(а никто не звонитforchild
) - нормально, но root-инжектор будет толькоservice1
. (доступно для всех приложений)Так зачем нам это нужно? Я бы сказал :
Вот и все.
Что ж - это скрыто в предложении выше ^
Конвенции (!!!) позволяет ему быть синглтон - или , чтобы быть более точным - если вы не будете следовать соглашению - вы НЕ получите синглтон.
Итак, если вы загружаете только
forRoot
вapp.module
, то вы получаете только один экземпляр, потому что вы должны вызыватьforRoot
его только вapp.module
.Кстати - на этом этапе можно забыть
forChild
. ленивый загруженный модуль не должен / не будет вызыватьforRoot
- так что вы в безопасности в POV синглтона.forRoot и forChild - это не один нерушимый пакет - просто нет смысла вызывать Root, который, очевидно, будет загружен только в,
app.module
без предоставления возможности для ленивых модулей, иметь свои собственные службы, без создания новых служб, которые должны быть -одинарный.Это соглашение дает вам прекрасную возможность, называемую
forChild
- потреблять «услуги только для ленивых загружаемых модулей».Вот демо Root-провайдеры дают положительные числа, ленивые загруженные модули дают отрицательные числа.
источник
В документации четко указано, какова цель этого различия здесь: https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root
Каждое приложение имеет ровно одну начальную точку (корень), в которой должна быть инициализирована основная служба маршрутизации
forRoot
, а маршруты для определенных «дочерних» функций должны регистрироваться дополнительноforChild
. Это чрезвычайно полезно для подмодулей и лениво загружаемых модулей, которые не нужно загружать при запуске приложения, и, как сказал @Harry Ninh, им предлагается повторно использовать RouterService вместо регистрации новой службы, что может вызвать ошибку времени выполнения.источник
Если appRoutes содержит путь к различным функциям на сайте (admin crud, user crud, book crud), и мы хотим разделить их, мы могли бы просто сделать это:
А для маршрутов:
источник