在 Angular 中,如何直接导航到延迟加载模块内的路径?

In Angular, how I navigate directly to a path inside a lazy loaded module?

我想要两个用于登录和注册的顶级路径。

我希望不必执行 auth/log-inauth/register

但是,auth 组件位于单独的模块中,这很好,因为除非特别要求,否则不应加载它。

export const routes: Route[] = [
  { path: 'log-in',   loadChildren: './auth-module/auth.module#AuthModule'},
  { path: 'register', loadChildren: './auth-module/auth.module#AuthModule'}
];

我在定义我的路由时如何指定我希望log-in路径转到log-in路径延迟加载的AuthModule中, 和 register 路径去 register 路径 inside 惰性加载模块?

您需要定义到达延迟加载的 AuthModule 时发生的情况。通过 creating/importing 使用 ModuleWithProviders 的 AuthModule 的路由文件来做到这一点。如果需要,可以添加子路由和路由器插座。

import { ModuleWithProviders } from '@angular/core';

export const authRoutes: Route[] = [

  { 
    path: '', 

 // path: '', redirects to children with no prefix in route
 // path: 'auth', prefix the route with 'auth' to create 'auth/log-in' 'auth/register'

    children: [                     
        { 
           path: 'log-in',
           component: LoginComponent,
          // outlet:'login' 
        },
        { 
            path: 'register', 
            component: RegisterComponent,
        //  outlet:'register' 
        },

        // redirects can be added to force the application to load your desired route 
       //{ path: '', redirectTo:'log-in' ,pathMatch:'full'},
    ]},
];
export const AuthRouting: ModuleWithProviders = RouterModule.forChild(authRoutes);

然后您的 AuthModule 导入这个路由文件。

//other imports
import {AuthRouting} from 'some/path/location';

@NgModule({
  imports: [
    CommonModule,
    AuthRouting,
    RouterModule
  ],

更新

即使是延迟加载的模块也可以定义一个空路由。

const APP_ROUTES: Routes = [
    { path: '', () => import('./app/auth/auth.module').then(m => m.AuthModule)},
];

并在您的延迟加载模块中定义两个组件的路径

const MODULE_ROUTES: Routes = [
    { path: 'login', component: LoginComponent},
    { path: 'register', component: RegisterComponent }
];

仅当组件路径匹配时才加载模块

原始遮阳棚

到目前为止,无法在 post 中像您希望的那样配置路由。如果您为路由器启用日志记录,您会看到这一点。您的模块(登录、注册)的路径已被消耗,在您的模块路由中,您将只剩下 '',无法与两个不同的组件匹配。

你可以实现这个 none 更少,即使它不是那么漂亮而且我不知道 how/if 它在旧的浏览器中工作。

在你的app.module.ts

const APP_ROUTES: Routes = [
    { path: 'login', redirectTo: 'auth/login', pathMatch: 'full' },
    { path: 'register', redirectTo: 'auth/register', pathMatch: 'full' },
    { path: 'auth', loadChildren: 'app/auth/auth.module#AuthModule', pathMatch: 'prefix'},
];

@NgModule( {
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        RouterModule,
        RouterModule.forRoot(APP_ROUTES)
    ],
    providers: [
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

auth.module.ts 看起来像这样

const ROUTES: Routes = [
    { path: 'login', component: LoginComponent, pathMatch: 'full' },
    { path: 'register', component: RegisterComponent, pathMatch: 'full' }
];

@NgModule( {
    imports: [
        CommonModule,
        RouterModule.forChild( ROUTES )
    ],
    declarations: [
        LoginComponent,
        RegisterComponent
    ]   
} )
export class AuthModule { }

然后您可以通过 <a routerLink="login">Login</a> 访问路线,也可以与 router.navigate 一起使用。不幸的是,即使客户端只调用 /login.

,这也会在浏览器中留下 auth/loginauth/register url

您可以通过在您的 window.history 中创建一个条目来解决这个问题 - 正如我所说的那样不漂亮,并且必须在您的组件构造函数中完成。 组件中的 window.history.pushState('register', 'Register', 'register');window.history.pushState('login', 'Login', 'login'); 将使您的浏览器 url 变为 /login/register.

最好的方法当然是使用此功能扩展 angular 路由器并将其用作自定义路由器,但您必须为此真正投入使用,并且在下一次更新中您可能搞砸了。

也许这对你有帮助

此致

export const routes: Route[] = [
  { path: 'log-in',   loadChildren: './auth-module/auth.module#AuthModule'},
  { path: 'register', loadChildren: './auth-module/auth.module#AuthModule'}
];

我会尽量说这不可能Lazy loading 个由重定向加载的模块。 这意味着:

  • 开始导航log-in
  • 懒加载模块开始加载
  • 加载成功后,url会变成somePath/log-in
  • 接下来呢?此处开始重定向过程。所以每个延迟加载模块的 routing.ts 应该包含 入口点路径 如:

    {
       path: '',
       redirectTo: 'somePath/ChildPath' // or component: SomeComponent
    }
    

不管它导航到哪条路线,如果它是一个惰性模块,那么它会尝试找到入口路径。在您的情况下,两条路由加载相同的模块,但它们也引用相同的入口路由路径 (path: '')

如果真的要分,应该分配到不同的模块中。

export const routes: Route[] = [
  { path: 'log-in',   loadChildren: './auth-module/someModule#someModule'},
  { path: 'register', loadChildren: './auth-module/auth.module#AuthModule'}
];

一些模块。routing.ts:

{
    path: '',
    component: LoginComponent,

},

更新 29.04.18。多一个组件的简单解决方案

解决方案是根据当前 url.

创建其他组件作为其他组件的 renderer

app-routing.module:

const appRoutes: Routes = [
 ...

  {
    path: 'admin',
    loadChildren: 'app/admin/admin.module#AdminModule',

  },
  {
    path: 'login',
    loadChildren: 'app/admin/admin.module#AdminModule',

  },
  {
    path: 'crisis-center',
    loadChildren: 'app/crisis-center/crisis-center.module#CrisisCenterModule',
    // data: { preload: true }
  },
  { path: '', redirectTo: '/superheroes', pathMatch: 'full' },
  { path: '**', component: PageNotFoundComponent }
];

admin.module中创建渲染器组件

central.component.ts:

...

@Component({
  selector: 'app-central',
  templateUrl: './central.component.html',
  styleUrls: ['./central.component.css']
})
export class CentralComponent implements OnInit {

  currentComponent: LoginComponent | AdminComponent;

  constructor(public router: Router, public activatedRoute: ActivatedRoute) { }

  ngOnInit() {
    if (this.router.url === '/login') {
      this.currentComponent = LoginComponent;
    } else {
      this.currentComponent = AdminComponent;
    }
  }
}

central.component.template:

<ng-container *ngComponentOutlet="currentComponent"></ng-container>

因此,如您所见,中心组件将根据 url 路径 动态呈现 组件。

渲染使用 声明性方法 方法和 NgComponentOutlet

有关命令式和声明式方法的更多详细信息:

StackBlitz Demo

app-routing 模块可以为功能模块的路由添加前缀(或不添加前缀)。如果你不想要像 /auth 这样的路由前缀,要么使用延迟加载要么不使用)你可以这样做:

应用-routing.module.ts:

  {
    path:             '',
    canActivate:      [AuthGuard],
    canActivateChild: [AuthGuard],
    children:         [
      {
        path:      '',
        component: HomeComponent,
      },
      {
        path:         '',
        loadChildren: 'app/auth/auth.module#AuthModule',
      },
      {
        path:      'settings',
        component: SettingsComponent,
      },
    ],
  },

懒加载模块的顶级路由甚至不必是静态的,你可以这样配置:

auth-routing.module.ts:

const routes: Routes = [
  {
    path:      ':pageName',
    component: AuthComponent,
    resolve:   {
      pageInfo: AuthResolver,
    },
    children:  [
      {
        path:      'login',
        component: LoginComponent,
      },
      {
        path:      'register',
        component: RegisterComponent,
      },
    ],
  },
];