Маршрутизатор-розетка не обновляется после навигации по Routerlink

Я создаю простое приложение Angular с меню навигации. Каждый пункт меню имеет Routerlink для перехода между страницами. Вот страницы:

  • Дом (#/home)
  • Клиент / Информация (#/customer/info)
  • Клиент / Подробности (#/customer/details)
  • Заказчик / Подробности / b0 (#/customer/details/b0)
  • Заказчик / Подробности / b1 (#/customer/details/b1)

Соответствующий код:

app.module.ts

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(
      [
        {
          path: "",
          redirectTo: "home",
          pathMatch: "full"
        },
        {
          path: "home",
          component: HomeComponent
        },
        {
          path: "customer",
          component: CustomerComponent,
          children: [
            {
              path: "",
              redirectTo: "info",
              pathMatch: "full"
            },
            {
              path: "info",
              component: CustomerInfoComponent,
            },
            {
              path: "details",
              component: CustomerDetailsComponent,
              children: [
                {
                  path: "",
                  redirectTo: "b0",
                  pathMatch: "full"
                },
                {
                  path: "b0",
                  component: CustomerDetailsBlock0Component
                },
                {
                  path: "b1",
                  component: CustomerDetailsBlock1Component
                },
              ]
            }
          ]
        }
      ],
      {useHash: true}
    )
    ],
  declarations: [ AppComponent, CustomerComponent, MenuComponent, HomeComponent, CustomerInfoComponent, CustomerDetailsComponent, CustomerDetailsBlock0Component, CustomerDetailsBlock1Component ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

customer-component.html

<p>This is customer #{{id}}</p>
<app-menu>
  <router-outlet></router-outlet>
</app-menu>

сведения о клиенте-component.html

<p>This is customer details</p>
<router-outlet></router-outlet>

сведения о клиенте-block0-component.html

<p>details block0</p>

сведения о клиенте-block1-component.html

<p>details block1</p>

menu-component.html

<div>
  <ul>
    <li>
      <a routerLink="">Home</a>
    </li>
    <li>
      <a routerLink="../customer">Customer</a>
      <ul>
        <li>
          <a routerLink="../customer/info">Info</a>
        </li>
        <li>
          <a routerLink="../customer/details">Details</a>
          <ul>
            <li>
              <a routerLink="../customer/details/b0">Block #0</a>
            </li>
            <li>
              <a routerLink="../customer/details/b1">Block #1</a>
            </li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
  <p>------------- Content inside menu router-outlet -------------</p>
  <router-outlet></router-outlet>
  <p>--------------------------------------------------------------------</p>
</div>

Навигация работает нормально: когда я нажимаю на ссылку, активированный маршрут изменяется, router-outlet обновляются и отображаются ожидаемые компоненты.

Проблема возникает, когда я обновляю страницу, когда маршрут #/customer/details/b1 (или если я нажимаю прямо на нем, не нажимая на элемент родительского меню): компоненты хорошие, но мое меню не работает. Если я нажму ссылку, чтобы перейти к #/customer/details/b0, маршрут будет изменен, но выход маршрутизатора не обновлен, компонент b1 по-прежнему отображается, а b0 - нет. Это исправлено, когда я нажимаю на другой пункт меню, URL-адрес которого не начинается с «клиент / подробности», например, если я нажимаю «Информация», проблема исчезает.

Angular_router_bug  Angular_router_bug_2

Я предполагаю, что проблема в том, что компонент customer-details является одним и тем же экземпляром, и поэтому Angular его повторно использует. Но тогда почему дочерние компоненты не меняются?

Мне удалось «исправить» это поведение, возвращая false каждый раз, когда вызывается функция маршрутизатора shouldReuseRoute :

// menu-component.ts
constructor(private router: Router) {
    this.router.routeReuseStrategy.shouldReuseRoute = () => false;
}

Но я не хочу каждый раз уничтожать / создавать все мои компоненты. Есть ли какие-то решения для этого?

Вот демонстрация Stackblitz. Чтобы воспроизвести ошибку:

  1. Перейдите по ссылке «Блок №1».
  2. Обновите окно вывода Stackblitz
  3. Нажмите «Блок № 0» или «Подробности»: маршрут изменен, но сообщение все еще остается «блок деталей 1».
  4. Щелкните "Информация".
  5. Повторите шаг 1. -> теперь проблема устранена.

РЕДАКТИРОВАТЬ: У меня все еще проблема с Angular v6.1.3 (я обновил демонстрация Stackblitz). Я пробовал все решения, предоставленные @ mast3rd3mon, но, похоже, ничего не исправляет.


person Junior Dussouillez    schedule 01.08.2018    source источник
comment
Я мог ошибаться, но я думал, что ссылка на маршрутизатор должна быть в скобках? [routerLink]="../customer"? это также может быть из-за того, что вы используете ../customer вместо /customer   -  person mast3rd3mon    schedule 01.08.2018


Ответы (3)


Проблема исходит от MenuComponent. Вы должны вставить <ng-content></ng-content> вместо <router-outlet></router-outlet>, потому что компонент, стоящий за <router-outler></router-outlet>, является init в компоненте, который вызывает MenuComponent (CustomerComponent в этом примере).

Итак, код в menu.component.html должен быть:

<p>------------- Content inside menu router-outlet -------------</p>
<ng-content></ng-content>
<p>--------------------------------------------------------------------</p>
person Dorian    schedule 29.08.2018

После просмотра созданной вами демонстрации вам необходимо удалить .. часть ссылок маршрутизатора. ../customer становится /customer, ../customer/info становится /customer/info и т. Д.

Возможно, это была просто демонстрация, но убедитесь, что файл app.component.html выглядит как <router-outlet></router-outlet>, а не <router-outlet>, поскольку тег должен иметь закрывающий тег.

person mast3rd3mon    schedule 01.08.2018
comment
Спасибо за ответ. Я обновил демонстрацию с помощью фиксированного тега маршрутизатора в app.component.html и .. в ссылках на маршрутизатор. Но проблема все та же. - person Junior Dussouillez; 01.08.2018
comment
вы остановились и снова запустили ng serve или что-то еще, что вы использовали? - person mast3rd3mon; 01.08.2018
comment
попробовав другие вещи, я удалил useHash, потому что я думаю, что это могло вызывать помехи. Я также RouterModule, выше RouterModule.forRoot(....), и я не могу воспроизвести вашу проблему сейчас - person mast3rd3mon; 01.08.2018
comment
Я удалил опцию useHash, но проблема все равно осталась. Я также пытался изменить ссылки маршрутизатора, используя [routerLinks] = ['/ customer / details / b0'] или [routerLinks] = ['/ customer', 'details', 'b0'], но, похоже, ничего не исправляет. - person Junior Dussouillez; 01.08.2018
comment
вы добавили RouterModule, над RouterModule.forRoot(....)? - person mast3rd3mon; 01.08.2018
comment
Да, я добавил это сверху и снизу, но это не имеет никакого эффекта. - person Junior Dussouillez; 01.08.2018
comment
странно, после этих изменений мне не удалось воспроизвести проблему - person mast3rd3mon; 01.08.2018

Объединить CustomerDetailsBlock0Component, CustomerDetailsBlock1Component в CustomerDetailsBlockComponent с параметром маршрута ': blockId'

CustomerDetailsBlockComponent{
   
  blockId: number

  constructor(private router Router){
        this.router.events.subscribe(event=>{
            if (event instanceof ActivationEnd && event.snapshot) {
                let blockId = +event.snapshot.paramMap.get('blockId')
                if (blockId) {
                    this.blockId = blockId
                    //update other angular bindings
                }
            }
        })
  }

}

person Abhinav Atul    schedule 03.11.2020