Angular: использование одного и того же <router-outlet> дважды в одном компоненте

Отказ от ответственности: это дубликат Изменение выхода маршрутизатора с помощью * ngIf в app.component.html в angular2, у которого есть принятый ответ, который, однако, не решает мою ситуацию.

Итак, вот моя проблема: я хотел бы иметь один и тот же «маршрутизатор» дважды в моем основном компоненте. Как кажется только второй "роутер-розетка" выигрывает и корректно отображает контент. Предлагаемое решение обернуть выход маршрутизатора в шаблон ng не работает для меня.

Это моя ситуация в коде:

<div class = "mobile-only">
  <div>some special content for mobile version</div>
  <router-outlet></router-outlet>
</div>

<div class = "desktop-only">
  <div>some special content for desktop version</div>
  <router-outlet></router-outlet>
</div>

Только второй маршрутизатор-выход обновляется, когда пользователь перемещается по странице. Первый роутер-розетка заброшен угловой.

Вопрос: Как повторно использовать роутер-розетку?

Обновлено: я попытался обернуть выход маршрутизатора в шаблон ng, но это не сработало: https://stackblitz.com/edit/router-outlet-in-template-not-working-example-cpyjbq

А вот рабочая версия: https://stackblitz.com/edit/router-outlet-in-template-working-example

На самом деле я могу повторно использовать маршрутизатор-выход --- но только за счет переназначения переменной шаблона в setTimeout. В качестве неприятного побочного эффекта компоненты воссоздаются.

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
3
0
2 410
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

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

Итак, если вы хотите использовать именованные розетки, вам нужно дать каждой розетке имя, например:

<div class = "mobile-only">
  <div>some special content for mobile version</div>
  <router-outlet name = "mobile-content"></router-outlet>
</div>

<div class = "desktop-only">
  <div>some special content for desktop version</div>
  <router-outlet name = "desktop-content"></router-outlet>
</div>

Затем вы можете перенаправить свои маршруты к определенному выходу в вашем файле маршрутизации следующим образом:

{
  path: 'mobile',
  component: MobileContentComponent,
  outlet: 'mobile-content'
},
{
  path: 'desktop',
  component: DesktopContentComponent,
  outlet: 'desktop-content'
}

Если вы перенаправляете на эти маршруты через директиву routerLink, вы можете перенаправить из шаблона следующим образом:

<a [routerLink] = "[{ outlets: { mobile-content: ['mobile'] } }]">Mobile Content</a>
<a [routerLink] = "[{ outlets: { desktop-content: ['desktop'] } }]">Desktop Content</a>

РЕДАКТИРОВАТЬ

Я только что видел ваш код на StackBlitz, и проблема в том, что вы дважды отображаете шаблон выхода маршрутизатора в шаблоне. Вам нужно отображать то или иное в зависимости от условия. Я изменил ваш StackBlitz здесь с помощью переменной, которая будет отображать тот или иной выход маршрутизатора в зависимости от условия (вы можете проверить размер экрана или что угодно).

Но, просматривая ваш код, я не понимаю, зачем вам две розетки маршрутизатора... Если вы хотите запустить класс только в родительском div розетки маршрутизатора, вы можете просто использовать ngClass для использования того или иного класса на основе экрана размер.

Спасибо за Ваш ответ! К сожалению, я не могу использовать разные маршруты для разных размеров экрана...

Tobias Gassmann 21.03.2019 17:31

Есть ли способ просто повторить одно и то же содержимое роутера-розетки? Я попытался поместить его в шаблон ng, но это тоже не сработало...

Tobias Gassmann 21.03.2019 17:33

Почему бы нет? Если вы запускаете перенаправление маршрута из файлов .ts, вы можете проверить размер экрана и загрузить тот или иной маршрут в зависимости от размера экрана. В любом случае, рекомендуемый подход состоял бы в том, чтобы иметь два разных приложения...

Elias Garcia 21.03.2019 17:34

Также да, я пробовал трюк с ng-template в более старом проекте, и он работал нормально... Можете ли вы поделиться некоторым кодом того, что вы пробовали в Stackblitz, чтобы помочь вам?

Elias Garcia 21.03.2019 17:40

(Роутер-выход мне понадобился дважды, потому что html-шаблон достаточно сложный и сложный, чем в моем примере на stackblitz) Еще раз спасибо! :-)

Tobias Gassmann 22.03.2019 12:07

У меня та же проблема, и использование разных маршрутов невозможно. Я попытался использовать пакет npm, который позволяет мне определять размеры экрана, но все равно правильно работает только второй выход, хотя в результирующем html есть только один выход.

eddy 03.06.2020 16:31

Я думаю, что нашел другое решение, слушая Router-Events:

https://stackblitz.com/edit/router-outlet-twice-with-events

В этом stackblitz у меня на самом деле есть два шаблона, одновременно использующих router-outlet. Это допустимый обходной путь?

Пытаясь найти работу для этого, я закончил с:

HTML

<div id = "mobile">
 <router-outlet *ngIf = "isMobile"></router-outlet>
</div>
<div id = "desktop">
 <router-outlet *ngIf = "isDesktop"></router-outlet>
</div>

ТС

export class ExampleComponent implements AfterViewInit {

  private initied: boolean
  constructor (
    private cdref: ChangeDetectorRef
  ) { }

  ngAfterViewInit (): void {
    this.initied = true
    this.cdref.detectChanges()
  }

  get isDesktop (): boolean {
    if (!this.initied) { return false }
    return this.checkHidden('router-mobile')
  }

  get isMobile (): boolean {
    if (!this.initied) { return false }
    return this.checkHidden('router-desktop')
  }

  private checkHidden (id: string): boolean {
    return (document.getElementById(id).getAttribute('style') as string).includes('display: none')
  }
}

Я пробовал что-то вроде следующего и помогает мне показать взаимоисключающие

HTML

<div id = "mobile">
 <router-outlet *ngIf = "!getIfMobile"></router-outlet>
</div>
<div id = "desktop">
 <router-outlet *ngIf = "getIfMobile"></router-outlet>
</div>

Компонент.ts

get getIfMobile() {
    return window.innerWidth < 720;
}

Хотя этот код может дать ответ на вопрос, предоставление дополнительного контекста относительно того, как и/или почему он решает проблему, улучшит долгосрочную ценность ответа.

Tomer Shetah 15.12.2020 14:37

Другие вопросы по теме