为什么没有<app-root>时,我的其他组件也无法显示在index.html上?

时间:2019-09-13 02:58:51

标签: angular typescript bootstrap-4 angular-components

我刚刚开始学习Angular并完成了一些教程。我的项目是由Angular CLI生成的。我已经在创建项目时生成的组件之上生成了一个名为navbar的新组件,并且试图查看启动时是否在我的index.html上加载了navbar。仅当两个应用都位于index.html文件中时,我的导航栏才会显示,例如:

<body>
  <app-root></app-root>
  <app-navbar></app-navbar>
</body>

如果我像这样从index.html中删除app-root:

<body>
  <app-navbar></app-navbar>
</body>

我的导航栏应用不再显示。这与app-root组件有关吗?是因为它是根组件,而且必须一直将其包含在index.html中?

这是我的代码:

index.html:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>DeepTier</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

<body>
  <app-navbar></app-navbar>
</body>

</html>

app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './component1/app.component';
import { NavbarComponent } from './navbar/navbar.component';

@NgModule({
  declarations: [
    AppComponent,
    NavbarComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [
    AppComponent,
    NavbarComponent
  ]
})
export class AppModule { }

navbar.component.ts:

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

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent {
  constructor() {}

  // tslint:disable-next-line: use-lifecycle-interface
  ngOnInit() {

  }
}

navbar.component.spec.ts:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { NavbarComponent } from './navbar.component';

describe('NavbarComponent', () => {
  let component: NavbarComponent;
  let fixture: ComponentFixture<NavbarComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ NavbarComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(NavbarComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

app.component.ts:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'DeepTier';
}

app.component.spec.ts:

import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  }));

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have as title 'DeepTier'`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app.title).toEqual('DeepTier');
  });

  it('should render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('.content span').textContent).toContain('DeepTier app is running!');
  });
});

3 个答案:

答案 0 :(得分:1)

您必须将组件选择器放置在app.component.html中:

<app-navbar></app-navbar>

<app-root> 标签是引导组件的显示位置(默认为 AppComponent )。通常,您不需要多个引导程序组件,因此请从AppModule的引导程序中删除NavbarComponent

在更高的杠杆视图中,您可以将应用视为组件树,其根是AppComponent,因此AppComponent的子代必须放置在app.component.html中,而NavBarComponent的子代必须位于放在navbar.component.html内。

答案 1 :(得分:0)

您可以将多个组件添加到引导程序,但是它们必须来自同一模块

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, HelloComponent, NavbarComponent ],
  bootstrap:    [ AppComponent ,NavbarComponent ]
})
export class AppModule { }

index.html

<my-app>loading</my-app>
<app-navbar>loading</app-navbar>

从单个模块(如此处的appmodule)启动角度应用程序

main.ts

platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {
  // Ensure Angular destroys itself on hot reloads.
  if (window['ngRef']) {
    window['ngRef'].destroy();
  }
  window['ngRef'] = ref;

  // Otherwise, log the boot error
}).catch(err => console.error(err));

demo ⚡⚡

答案 2 :(得分:0)

Angular尝试找到应用程序根标记,并引发错误,您可以在浏览器的控制台中看到以下内容:

错误:选择器“ app-root”与任何元素都不匹配 在ha.selectRootElement(main-*。js)

因此渲染崩溃,导航栏不显示

为避免此问题,请在根应用模块中添加带有条件的ngDoBootstrap方法:

@NgModule({
  declarations: [],
  imports: [BrowserModule, AppRoutingModule],
  providers: [],
  bootstrap: []
})
export class AppModule
{
  ngDoBootstrap(appRef: ApplicationRef)
  {
    if (document.getElementsByTagName('app-root').length > 0)
    {
      appRef.bootstrap(AppComponent, 'app-root')
    }
    if (document.getElementsByTagName('app-navbar').length > 0)
    {
      appRef.bootstrap(NavbarComponent, 'app-navbar')
    }
  }
}