首页 > 解决方案 > Angular 6 - 动态子路由

问题描述

我正在学习 Angular 6,但我被困在了路由器上。⛔️

应用程序路由.module.ts

import { NgModule } from '@angular/core';
import { WeatherComponent } from './weather/weather.component';
import { ForecastComponent } from './forecast/forecast.component';
import { ForecastDailyComponent } from './forecast-daily/forecast-daily.component';
import { ForecastResolverService } from './shared/services/resolvers/forecast-resolver.service';
import { ForecastDailyResolverService } from './shared/services/resolvers/forecast-daily-resolver.service';

import { RouterModule, Routes, PreloadAllModules } from '@angular/router';

export const routes: Routes = [
  {
    path: '',
    component: WeatherComponent,
    pathMatch: 'full',
  },
  {
    path: ':name',
    component: ForecastComponent,
    resolve: {
      forecast: ForecastResolverService,
    },
    children: [
      {
        path: ':day',
        // i had here pathMatch: 'full', does not help
        component: ForecastDailyComponent,
        resolve: {
          forecast: ForecastDailyResolverService
        }
      }
    ]
  },
  {
    path: '**',
    redirectTo: '',
    pathMatch: 'full'
  }
];
const ENABLE_TRACING = true;

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

预测解析器.service.ts

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Resolve } from '@angular/router';

import { WeatherForecastPayload } from '../../../shared/models/weather-forecast-payload.model';
import { WeatherService } from '../../../shared/services/weather.service';
import { CityService } from '../../../shared/services/city.service';
import { Observable } from 'rxjs';

@Injectable()
export class ForecastResolverService implements Resolve<WeatherForecastPayload> {

  constructor(
    private weatherService: WeatherService,
    private cityService: CityService,

  ) { }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<WeatherForecastPayload> {
    const name = route.paramMap.get('name');
    const forecast = this.weatherService.getForecast(this.cityService.getCityID(name));
    return forecast;
  }
}

每日预测resolver.sevice.ts

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Resolve } from '@angular/router';

import { WeatherForecast } from '../../models/weather-forecast.model';
import { StoreService } from '../../services/store.service';
import { WeatherForecastPayload } from '../../models/weather-forecast-payload.model';
import { getWeekDayNumber } from '../../utils/converters';

@Injectable()
export class ForecastDailyResolverService implements Resolve<Array<WeatherForecast>> {

  constructor(
    private store: StoreService,
  ) { }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    const day = route.paramMap.get('day');

    const forecast: WeatherForecastPayload = this.store.get('forecast');

    const dailyForecast = forecast.list.filter(
      (item) => {
        const forecastDay = getWeekDayNumber(String(new Date(item.dt_txt).getDay()));
        if (day === forecastDay) {
          return item;
        }
      }
    );
    return dailyForecast;
  }
}

带有指向 /:name 路由的链接的 weather.component.ts

<div class="jumbotron-fluid h-100 text-center m-0 d-flex flex-column justify-content-center">
  <div class="container-fluid h-100">
    <div class="row h-100">
      <div *ngFor="let weather of weatherList" class="col-lg m-4">
        <!-- weather.name ends up being London,Berlin or other city -->
        <app-weather-card [routerLink]="[weather.name]" [weather]="weather">
        </app-weather-card>
      </div>
    </div>
  </div>
</div>

带有指向 /:name/:day 路线的链接的 forecast.component.ts

<div class="jumbotron-fluid h-100 text-center m-0 d-flex flex-column justify-content-center">
  <div class="container-fluid h-100">
    <div class="row h-100">
      <div *ngFor="let dailyForecastList of forecastList" class="col-lg m-4">
        <app-forecast-card
          <!-- getDay() returns Mon or Thu or Fri etc. -->
          [routerLink]="[getDay(dailyForecastList.dt_txt)]"
          [forecast]="dailyForecastList">
        </app-forecast-card>
      </div>
    </div>
  </div>
</div>
<router-outlet></router-outlet>

app.module.ts

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

import { AppComponent } from './app.component';
import { SharedModule } from './shared';
import { WeatherModule } from './weather/weather.module';
import { ForecastModule } from './forecast/forecast.module';
import { ForecastDailyModule } from './forecast-daily/forecast-daily.module';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    SharedModule,
    BrowserModule,
    WeatherModule,
    ForecastModule,
    ForecastDailyModule,
    AppRoutingModule,
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

shared.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';


import { WeatherIconComponent } from './components/weather/weather-icon/weather-icon.component';
import { WeatherTemperatureComponent } from './components/weather/weather-temperature/weather-temperature.component';
import { WeatherCardComponent } from './components/weather/weather-card/weather-card.component';
import { ForecastCardComponent } from './components/weather/forecast-card/forecast-card.component';
import { NavigationComponent } from './components/navigation/navigation.component';
import { FooterComponent } from './components/footer/footer.component';

import { StoreService } from '../shared/services/store.service';


@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    RouterModule,
    ReactiveFormsModule,
    HttpClientModule,
  ],
  exports: [
    CommonModule,
    FormsModule,
    RouterModule,
    ReactiveFormsModule,
    HttpClientModule,
    WeatherIconComponent,
    WeatherTemperatureComponent,
    WeatherCardComponent,
    ForecastCardComponent,
    NavigationComponent,
    FooterComponent,
  ],
  declarations: [
    WeatherIconComponent,
    WeatherTemperatureComponent,
    WeatherCardComponent,
    ForecastCardComponent,
    NavigationComponent,
    FooterComponent,
  ],
  providers: [StoreService],
})
export class SharedModule {}

store.service.ts用于保存全局数据的简单存储

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable()
export class StoreService {

  constructor() { }

  protected store$: Map<string, any> = new Map();
  public subject = new BehaviorSubject(this.store$);

  public get(key: any): any {
    return this.store$.get(key);
  }

  public set(key: any, value: any) {
    this.store$.set(key, value);
  }

}

在被天气组件覆盖的入口路线“”上,您可以看到包含 5 个位置的天气列表,当单击其中一个位置时,路由器将我们引导到 /:name 并行路线,您可以在该路线中看到未来 5 天的预报行的形式,单击其中一个会导致我们看到当天/:name/:day的每小时预测列表,但我可以看到来自':name'的内容,我希望只看到每小时预测列表。

如果需要,我可以添加更多文件,但我认为我发布了最相关的。

谢谢。

标签: angularangular-router

解决方案


经过多次尝试和 100 个看到的示例(其中没有一个进入这个方向),我决定尝试这个路由器配置并且它有效,希望它对某人有所帮助。

应用程序路由.module.ts

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

import { WeatherComponent } from './weather/weather.component';
import { ForecastComponent } from './forecast/forecast.component';
import { ForecastDailyComponent } from './forecast-daily/forecast-daily.component';
import { ForecastResolverService } from './shared/services/resolvers/forecast-resolver.service';
import { ForecastDailyResolverService } from './shared/services/resolvers/forecast-daily-resolver.service';

import { RouterModule, Routes, PreloadAllModules } from '@angular/router';

export const routes: Routes = [
  {
    path: '',
    component: WeatherComponent,
  },
  {
    path: ':name',
    component: ForecastComponent,
    resolve: {
      forecast: ForecastResolverService,
    }
  },
  {
    path: ':name/:day',
    component: ForecastDailyComponent,
    resolve: {
      forecast: ForecastDailyResolverService
    }
  },
  {
    path: '**',
    redirectTo: '',
    pathMatch: 'full'
  }
];

const ENABLE_TRACING = false;

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

推荐阅读