Использование useHash: true прерывает открытие маршрутов Angular на новой странице

Я пытаюсь открыть маршрут Angular в новой вкладке, и у меня возникли проблемы после добавления {useHash: true} в маршрутизатор. Он работал нормально до того, как попробовал useHash, открыл вкладку и сразу перешел к нужному мне компоненту. Теперь кажется, что независимо от того, какой URL я использую для открытия новой вкладки, маршрутизатор думает, что я пытаюсь получить root ("/").

Для воспроизведения у меня есть очень простой угловой роутер:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Page2Component } from './page2.component';
import { Page1Component } from './page1.component';

const routes: Routes = [
    { 
        path: 'page1', 
        component: Page1Component
    },
    {
        path: 'page2',
        component: Page2Component
    },
  { 
        path: '',
        component: Page1Component
    }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, {useHash: true})],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Это позволяет просматривать 2 простых компонента:

/Страница 1

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-page1',
  template: `<p>page1 works!</p>
             <button (click)="openNewTab()">OPEN NEW TAB</button>`,
  styleUrls: ['./app.component.css']
})
export class Page1Component implements OnInit {

    constructor(private router:Router) { }

    ngOnInit(): void {
    }

    openNewTab():void {
        console.log('Opening new tab...');
        const url = this.router.serializeUrl(
            this.router.createUrlTree(['page2'])//, 
        );
        window.open(url);
    }
}

/страница 2

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-page2',
  template: `<p>page2 works!</p>`,
  styleUrls: ['./app.component.css']
})
export class Page2Component implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

По сути, когда вы нажимаете кнопку, расположенную на some.url.com/#/page1, Angular должен открывать новую вкладку, на которой отображается some.url.com/#/page2. На самом деле, как я ясно вижу, он пытается открыть some.url.com/page2. Обратите внимание на отсутствие /#. Теперь, если я установлю для useHash значение false, я могу перейти с some.url.com/page1 на some.url.com/page2, без проблем. Я попытался вручную добавить / # к открытому URL-адресу примерно 10 различными способами, но независимо от того, что я пытаюсь сделать, маршрутизатор видит URL-адрес новой вкладки как / (root), пока включен useHash.

Что мне здесь не хватает?

Я буду полностью честен, что я не очень разбираюсь во внутренней работе Angular HashLocationStrategy. Документация и обширные исследования не помогают. Я знаю, что мне действительно нужно использовать HashLocationStrategy из-за конфигурации сервера, на котором в конечном итоге будет размещено фактическое приложение, поэтому, к сожалению, я не могу усложнить задачу и просто установил для useHash значение false. Мне также нужно сделать это изнутри компонента, так как у меня есть обширная логика, которую мне нужно выполнить перед открытием новой вкладки в моем реальном приложении, поэтому в html тоже нет routerLink. У меня такое чувство, что мне здесь не хватает чего-то простого и фундаментального...

Любая помощь будет принята с благодарностью.

Рабочая минимальная репликация Stackblitz: https://stackblitz.com/edit/angular-ivy-yedwyk

2 ответа

Используйте location.prepareExternalUrl(). Определение метода prepareExternalUrl() из документации Angular ,

Нормализует внешний путь URL. Если данный URL-адрес не начинается с косой черты ('/'), добавляется перед нормализацией. Добавляет хэш, если используется HashLocationStrategy, или APP_BASE_HREF, если используется PathLocationStrategy.

Местоположение импорта из Angular Common:

      import { Location } from '@angular/common';    

Добавить службу определения местоположения в конструктор:

      constructor(private router:Router,
            private location: Location) { }

Используйте this.location.prepareExternalUrl, чтобы создать URL-адрес с # внутри него, чтобы вы могли открыть его с помощью window.open(url):

      openNewTab():void {
    console.log('Opening new tab...');
    const url = this.location.prepareExternalUrl(this.router.serializeUrl(
        this.router.createUrlTree(['page2'])
    ));
    window.open(url);
}

Поздно, но надеюсь, что это поможет кому-то другому.

Во-первых, вы пытаетесь странным образом перемещаться по приложению. Просто используйте следующий подход:

      this.router.navigate(['/page2']);

Вы должны использовать экземпляр маршрутизатора, чтобы правильно разрешить навигацию. Также используйте свойство routerLink при использовании тегов:

      <a routerLink="/page2">Navigate to /page2</a>
Другие вопросы по тегам