javascript - Angular 4 路由奇怪的行为 : not rendering child module unless on page refresh

标签 javascript node.js twitter-bootstrap angular typescript

我一直在寻找解决这种奇怪行为的方法,但没有成功。

  • angular 4 控制台或 javascript 控制台没有错误
    • 使用 Angular CLI(Angular 4)

我在使用 Angular 路由器时出现了极其奇怪的行为。我试图从父 AppModule 加载一个子路由,它有自己的模块。路线在/products

在/products 模块 (products.module.ts):我有 3 条路线:

  1. /产品/概览
  2. /products/intro [从/products 重定向到]
  3. /产品/产品/:产品

products 模块应该在全局 AppModule 的导航栏下有自己的导航栏,它在 products.component.html 组件模板中的路由器导出之上。

主要问题:当我将页面(不使用 Angular routerLink)加载到/products 时:

  • 两个导航栏都可见
  • 已加载的页面(例如/intro)的导航栏可见,但子组件 (IntroComponent) 可见
  • 但是,当我导航到/products 模块路由中的任何其他子路由时(例如/overview 或/product/:product):它呈现得很好。因此,在整个页面刷新时加载的任何路由都是不可见的。

最奇怪的部分:当我在不是/products(例如/home)的路径上加载(刷新)页面,然后使用主导航栏导航到/products 时:

  • 导航栏不可见 ??????
  • 子组件(ex/intro 组件)可见

在过去的几天里,这让我非常痛苦。

现在,一些代码:

app.module.ts [主 AppModule]

    @NgModule({
    declarations: [
        AppComponent,
        HomeComponent,
        LoginComponent,
        SignupComponent,
        NotFoundComponent,
        LogoutComponent,
        ErrorComponent,
        AboutComponent,
        ApiComponent,
        StatusComponent,
        SupportComponent,
        CustomersComponent,
        JobsComponent,
        TosComponent
    ],
    imports: [
        BrowserModule,
        HttpModule,
        FormsModule,
        SharedModule,
        //ProductsModule,
        AppRoutingModule
    ],
    providers: [
        UserService,
        AuthGuard,
        ErrorService,
        NavbarService,
        MailerService,
        IOService,
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}

shared.module.ts -- 这有我的 ViewAppComponent(它只是一个带有全局导航栏的路由器导出)和其他全局组件(比如应该在所有路由上显示的导航栏和页脚)

@NgModule({
  imports: [
    CommonModule,
      RouterModule
  ],
  declarations: [ViewAppComponent, FooterComponent, NavbarComponent],
  exports: [CommonModule, ViewAppComponent, FooterComponent, NavbarComponent]
})
export class SharedModule { }

app-routing.module.ts

const routes: Routes = [
    {
        path: '',
        component: ViewAppComponent,
        children: [
            {path: 'products', loadChildren: () => ProductsModule}, // where im trying to load my products module from the main module
            {path: 'home', component: HomeComponent},
            {path: 'about', component: AboutComponent},
            {path: 'api', component: ApiComponent},
            {path: 'status', component: StatusComponent},
            {path: 'support', component: SupportComponent},
            {path: 'customers', component: CustomersComponent},
            {path: 'jobs', component: JobsComponent},
            {path: 'tos', component: TosComponent},
            {path: 'signup', component: SignupComponent, canActivate: [AuthGuard]},
            {path: 'logout', component: LogoutComponent, canActivate: [AuthGuard]},
            {path: 'login', component: LoginComponent},
            {path: 'error', component: ErrorComponent, canActivate: [ErrorService]},
            {path: "404", component: NotFoundComponent},
            {path: '', redirectTo: '/home', pathMatch: 'full'},
        ]
    },
    {path: "admin", loadChildren: "./admin/admin.module#AdminModule"},
    {path: '**', redirectTo: '/404'}
];

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

products.module.ts [我尝试加载子路径的主要产品模块]

@NgModule({
    imports: [
        CommonModule,
        FormsModule,
        SharedModule,
        RouterModule,
        ProductsRoutingModule
    ],
    declarations: [ProductsComponent, OverviewComponent, IntroComponent, NavigationComponent, ProductComponent],
    exports: [
        ProductsComponent, OverviewComponent, IntroComponent, NavigationComponent, ProductComponent, RouterModule, ProductsRoutingModule
    ]
})
export class ProductsModule {
}

products-routing.module.ts [产品子模块的路由器]

export const productRoutes: Routes = [
    {
        path: '',
        component: ProductsComponent,
        children: [
            {
                path: 'overview',
                component: OverviewComponent,
            },
            {
                path: 'intro',
                component: IntroComponent
            },
            {
                path: 'product/:product',
                component: ProductComponent
            },
            {
                path: '',
                redirectTo: '/products/intro',
                pathMatch: 'full'
            },
            {
                path: '**',
                redirectTo: '/404',
                pathMatch: 'full'
            }
        ]
    }
];

@NgModule({
    imports: [RouterModule.forChild(productRoutes)],
    exports: [RouterModule]
})
export class ProductsRoutingModule {}

products.component.html [带有产品子组件导出的产品模板]

<h1>Products</h1>
<br/>
<app-product-navigation></app-product-navigation>
<br/>
<router-outlet></router-outlet>

navigation.component.html [app-product-navigation 组件模板]

<nav class="navbar navbar-info" role="navigation">
  <div class="container-fluid">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#products-navbar-collapse">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
    </div>

    <div class="collapse navbar-collapse" id="products-navbar-collapse">
      <ul class="nav navbar-nav">
        <li routerLinkActive="active"><a routerLink="/products/intro">Intro</a></li>
        <li routerLinkActive="active"><a routerLink="/products/overview">Overview</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown">Products <b class="caret"></b></a>
          <ul class="dropdown-menu">
            <li routerLinkActive="active"><a routerLink="/products/product/reflex">Reflex</a></li>
            <li routerLinkActive="active"><a routerLink="/products/product/override">Project Override</a></li>
          </ul>
        </li>
      </ul>
    </div>
  </div>
</nav>
<br/>

我还将提供版本的 package.json 依赖项,我正在使用 ng serve 进行测试。

  "dependencies": {
    "@agm/core": "1.0.0-beta.0",
    "@angular/animations": "4.3.1",
    "@angular/cdk": "2.0.0-beta.10",
    "@angular/common": "4.3.1",
    "@angular/compiler": "4.3.1",
    "@angular/core": "4.3.1",
    "@angular/forms": "4.3.1",
    "@angular/http": "4.3.1",
    "@angular/material": "2.0.0-beta.10",
    "@angular/platform-browser": "4.3.1",
    "@angular/platform-browser-dynamic": "4.3.1",
    "@angular/platform-server": "4.3.1",
    "@angular/router": "4.3.1",
    "angular2-material-datepicker": "0.5.0",
    "animate.css": "3.5.2",
    "arrive": "2.3.1",
    "bootstrap": "3.3.5",
    "bootstrap-material-design": "0.5.10",
    "bootstrap-notify": "3.1.3",
    "bootstrap-select": "1.12.2",
    "bootstrap-tagsinput": "0.7.1",
    "chartist": "0.9.4",
    "chartist-plugin-zoom": "0.4.0",
    "core-js": "2.4.1",
    "datatables": "1.10.12",
    "datatables.net-bs": "1.10.12",
    "datatables.net-responsive": "2.1.1",
    "eonasdan-bootstrap-datetimepicker": "4.17.47",
    "fullcalendar": "3.4.0",
    "googleapis": "19.0.0",
    "jasny-bootstrap": "3.1.3",
    "jquery": "1.12.4",
    "moment": "2.18.1",
    "moment-timezone": "0.4.0",
    "ng2-nouislider": "1.6.1",
    "ng2-select": "1.2.0",
    "ngx-chips": "1.4.6",
    "nouislider": "9.2.0",
    "rxjs": "^5.4.2",
    "twitter-bootstrap-wizard": "1.2.0",
    "typescript": "2.3.4",
    "validate": "3.0.1",
    "web-animations-js": "2.2.2",
    "zone.js": "0.8.4"
  },
  "devDependencies": {
    "@angular/cli": "1.4.2",
    "@angular/compiler-cli": "4.3.1",
    "@types/bootstrap": "3.3.32",
    "@types/chartist": "0.9.34",
    "@types/jasmine": "2.5.38",
    "@types/jquery": "1.10.31",
    "@types/node": "6.0.73",
    "codelyzer": "2.0.0",
    "jasmine-core": "2.5.2",
    "jasmine-spec-reporter": "3.2.0",
    "karma": "1.4.1",
    "karma-chrome-launcher": "2.0.0",
    "karma-cli": "1.0.1",
    "karma-coverage-istanbul-reporter": "0.2.0",
    "karma-jasmine": "1.1.0",
    "karma-jasmine-html-reporter": "0.2.2",
    "node-sass": "^4.5.3",
    "protractor": "5.1.0",
    "ts-node": "2.0.0",
    "tslint": "4.5.0",
    "typescript": "2.3.4"
  }
}

这是我在 stackoverflow 上的第一篇“寻求帮助”帖子,如果有任何我可以改进的地方,请告诉我。

我尝试研究各种表格和教程并引用了 angular docs for routing

编辑:添加一些图片以更清楚地说明情况

首页:http://prntscr.com/gskex5

产品 [/products/intro](使用 routerLink 导航):http://prntscr.com/gskf2h (缺少产品导航栏) 刷新时,导航栏可见,但介绍组件消失了:http://prntscr.com/gskfaq

但是,当我单击产品导航中的另一个组件时,它可以正常工作:http://prntscr.com/gskfhf

如果我刷新,组件会消失,导航会留下:http://prntscr.com/gskfna 现在,无论出于何种原因,如果我回到简介,它会正常工作:http://prntscr.com/gskfra

所以基本上,无论在初始加载页面时加载什么路由,它都会出现问题[组件不可见]。如果最初加载的路由不是/products;产品导航栏不可见。

最佳答案

对于这种相当奇怪的情况,我能够通过使用 angular-cli 生成一个新的 Angular 4 应用程序来修复这种奇怪的行为:ng new

我猜这与我运行的 Angular 版本有关。

对于我的新项目,@angular 版本设置为 **^4.0.0*。

在旧项目中,版本设置为 4.3.1

我猜这与 v4.3.1 的错误修复中的一项更改有关:

  • router: canDeactivate guards should run from bottom to top (1ac78bf), closes #15657
  • router: should navigate to the same url when config changes (4340bea), closes #15535
  • router: should run resolvers for the same route concurrently (ec89f37), closes #14279
  • router: terminal route in custom matcher (5d275e9)

长话短说

使用最新稳定版的ng4

关于javascript - Angular 4 路由奇怪的行为 : not rendering child module unless on page refresh,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46536562/

相关文章:

javascript - 动态更改 jQuery 选择器中的样式

node.js - 如何使用 MongoDb 在 NodeJS 中获取收件箱的 session 用户及其最后消息

javascript - 使用 Jade Html 预处理器分别在每个 div 内包含一个 img 标签的多个 Div

html - 如何使用 col-sm-3 在 Bootstrap 中向网格的左侧和右侧添加填充,而不在网格框之间添加填充

css - Bootstrap - 无法覆盖伪类的属性

javascript - 在我的 javascript 中永远不会触发成功事件以进行轮询事件

javascript - 从表中查询值

javascript - 为什么多次调用 Array.fill 会影响未引用的数组?

mysql - 从 mySQL 返回未定义

html - CSS 中的水平 block 对齐