【问题标题】:Understand Angular 8 routing了解 Angular 8 路由
【发布时间】:2026-02-02 23:40:02
【问题描述】:

为了熟悉 Angular,我改编了一个在互联网上找到的示例 (cornflourblue)。 它由一个控制 AppComponent、一个 LoginComponent 和一个 HomeComponent 组成。 路由是这样定义的:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';

import { HomeComponent } from './home';
import { LoginComponent } from './login';   

const routes: Routes = [
  { path: 'home',  component: HomeComponent },
  { path: 'login', component: LoginComponent }
];

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

但是我使用 URL 没有区别:localhost:4200、localhost:4200/home 或 localhost:4200/login - 我总是看到用 login.component.html 定义的页面。

AppCpmponent 是这样的:

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

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

LoginComponent 是这样的(为了简单起见,我删除了所有逻辑):

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Credentials } from '@app/_models';

@Component({ 
    selector: 'app-login',
    templateUrl: 'login.component.html' 
})

export class LoginComponent implements OnInit {
loginForm: FormGroup;
loading = false;
submitted = false;
returnUrl: string;
error = '';

constructor(
    private formBuilder: FormBuilder,
    private route: ActivatedRoute,
    private router: Router,
) {     }

ngOnInit() {
    this.loginForm = this.formBuilder.group({
        username: ['', Validators.required],
        password: ['', Validators.required]
    });

    // get return url from route parameters or default to '/'
    this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
}

// convenience getter for easy access to form fields
get f() { return this.loginForm.controls; }

onSubmit() {
    this.submitted = true;

    // stop here if form is invalid
    if (this.loginForm.invalid) {
        return;
    }
    this.loading = true;           
}

getCredentials(aUsername: string, aPassword: string) {
    let credentials: Credentials = {username :aUsername, password : aPassword};
    console.log("Entered credentials: User=" + credentials.username + " User=" + credentials.password);
    return credentials;

}

}

这是 HomeComponent:

import { Component } from '@angular/core';
import { first } from 'rxjs/operators';

import { User } from '@app/_models';
import { UserService } from '@app/services';

@Component({ templateUrl: 'home.component.html' })
export class HomeComponent {
    loading = true;
    users: User[];
}

这是使用的 html: app.component.html

<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
  <header class="mdl-layout__header">
    <div class="mdl-layout__header-row">
      <span class="mdl-layout-title">Authentication</span>
      <div class="mdl-layout-spacer"></div>
      <nav class="mdl-navigation mdl-layout--large-screen-only">
        <a class="mdl-navigation__link" [routerLink]="['/']">Home</a>
        <a class="mdl-navigation__link" (click)="logout()">Logout</a>        
      </nav>
    </div>
  </header>
  <app-login>
      <router-outlet></router-outlet>
  </app-login>
</div>

home.component.html

<div class="card mt-4">
    <h4 class="card-header">You're logged in with Angular 8 & Basic HTTP Authentication!!</h4>
    <div class="card-body">
        <h6>Users from secure api end point</h6>
    </div>
</div>

login.component.html

<div class="col-md-6 offset-md-3 mt-5">
    <div class="card">
        <h4 class="card-header">Angular 8 Basic Auth Login Example</h4>
        <div class="card-body">
            <form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
                <div class="form-group">
                    <label for="username">Username</label>
                    <input type="text" formControlName="username" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.username.errors }" />
                    <div *ngIf="submitted && f.username.errors" class="invalid-feedback">
                        <div *ngIf="f.username.errors.required">Username is required</div>
                    </div>
                </div>
                <div class="form-group">
                    <label for="password">Password</label>
                    <input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
                    <div *ngIf="submitted && f.password.errors" class="invalid-feedback">
                        <div *ngIf="f.password.errors.required">Password is required</div>
                    </div>
                </div>
                <button [disabled]="loading" class="btn btn-primary">
                    <span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
                    Login
                </button>
                <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>
            </form>
        </div>
    </div>
</div>

基本的 index.html 是:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Authentication</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="https://storage.googleapis.com/code.getmdl.io/1.0.1/material.indigo-orange.min.css">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
  <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" />
</head>
<body>
  <app-root>Loading...</app-root>
</body>
</html>

我已经花了很多时间尝试减少代码,将其更改为阅读文档 - 但无法查看 HomeComponent - 但无法进一步了解。感谢您的帮助

【问题讨论】:

  • 为什么你的router-outlet insideapp.component.html 中有一个app-login 组件?这可能是问题所在。
  • 正如理查兹所说的“app.component”必须拥有&lt;router-outlet&gt;

标签: angular routing


【解决方案1】:

你在 app.component.html 中有错误的代码。

<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
  <header class="mdl-layout__header">
    <div class="mdl-layout__header-row">
      <span class="mdl-layout-title">Authentication</span>
      <div class="mdl-layout-spacer"></div>
      <nav class="mdl-navigation mdl-layout--large-screen-only">
        <a class="mdl-navigation__link" routerLink="/home">Home</a>
        <a class="mdl-navigation__link" routerLink="/login">Login</a>
        <a class="mdl-navigation__link" (click)="logout()">Logout</a>        
      </nav>
    </div>
  </header>
  <router-outlet></router-outlet>
</div>

复制并粘贴此代码。

如果您希望 HomeComponent 出现在路由器中的主页上,例如 www.sadaasd.com/:

const routes: Routes = [
  { path: '',  component: HomeComponent }, // empty path
  { path: 'login', component: LoginComponent }
];

当你有一个组件声明为路由时,不要在任何地方使用 &lt;app-login&gt; 标签 &lt;router-outlet&gt; 决定何时显示它。

app.component.html 中的示例bobo.com/home 代替&lt;router-outlet&gt; 将显示home.component.html,而bobo.com/login 将有login.component.html。这是根据path: 'home'path: 'login'

【讨论】:

  • 我从“Routes”中的空路径开始,然后将空路径和“home”路径都指向 HomeComponent,以允许指定 url ../home。你是对的,到目前为止,app.component.html 是错误的,“主页”的导航会指向错误的路径 - 但对于我的示例,这没有任何意义 - 我没有点击链接。但是您对 -tag 是正确的,这不能在 app.component.html 中设置。我改变了它,现在正在与另一个错误作斗争。非常感谢