Angular跨组件数据传递:点击城市切换天气API数据方案
Angular城市天气切换实现方案
问题描述
学习Angular时遇到组件间数据传递与动态加载数据的问题:首页有四个城市(伦敦、纽约、东京、悉尼),点击任意城市后跳转到天气数据组件,需根据点击的城市动态修改WeatherService中API请求的经纬度,展示对应城市的天气数据(温度、湿度等),当前数据固定为伦敦的默认值。
实现步骤
1. 首页组件:传递城市经纬度参数
修改首页组件HTML,给每个城市的路由链接添加对应经纬度的查询参数:
<div class="container"> <div class="grid"> <a routerLink="/weather-data" [queryParams]="{lat: '51.51', lon: '-0.13'}"> <h3>London</h3> </a> <a routerLink="/weather-data" [queryParams]="{lat: '40.71', lon: '-74.01'}"> <h3>New York</h3> </a> <a routerLink="/weather-data" [queryParams]="{lat: '35.67', lon: '139.65'}"> <h3>Tokyo</h3> </a> <a routerLink="/weather-data" [queryParams]="{lat: '-33.87', lon: '151.21'}"> <h3>Sydney</h3> </a> </div> </div>
2. 天气数据组件:接收参数并加载对应数据
修改WeatherDataComponent,注入路由服务监听参数变化,动态请求对应城市数据:
import { ActivatedRoute, ParamMap } from '@angular/router'; // ...保留原有导入 export class WeatherDataComponent implements OnInit, OnDestroy { // ...保留原有属性 private currentLat: string = '51.51'; private currentLon: string = '-0.13'; constructor( private weatherService: WeatherService, public datePipe: DatePipe, private route: ActivatedRoute // 新增路由注入 ) { // ...保留原有构造函数内容 } ngOnInit(): void { this.weatherDataLoading = true; // 监听路由参数变化,支持组件复用场景下的城市切换 this.route.queryParamMap.pipe( takeUntil(this.componentDestroyed$) ).subscribe((paramMap: ParamMap) => { const lat = paramMap.get('lat'); const lon = paramMap.get('lon'); if (lat && lon && (lat !== this.currentLat || lon !== this.currentLon)) { this.currentLat = lat; this.currentLon = lon; this.loadWeatherData(); } else if (!this.weatherData.length) { this.loadWeatherData(); // 首次加载默认数据 } }); this.loading = true; } // 提取数据加载逻辑为独立方法 private loadWeatherData(): void { this.weatherDataLoading = true; this.weatherData = []; // 清空旧数据 this.lazyWeatherData = []; // 清空懒加载缓存 this.weatherService .getWeatherData(this.currentLat, this.currentLon) .pipe( finalize(() => (this.weatherDataLoading = false)), takeUntil(this.componentDestroyed$) ) .subscribe({ next: (historicalWeatherData) => { const temperatures = historicalWeatherData.hourly.temperature_2m; const times = historicalWeatherData.hourly.time.map((time) => this.datePipe.transform(time, 'shortTime') ); const humidities = historicalWeatherData.hourly.relativehumidity_2m; const windSpeeds = historicalWeatherData.hourly.windspeed_10m; const airPressures = historicalWeatherData.hourly.surface_pressure; const windDirections = historicalWeatherData.hourly.winddirection_10m; const precipitations = historicalWeatherData.hourly.precipitation; const rain = historicalWeatherData.hourly.rain; const cloudcover = historicalWeatherData.hourly.cloudcover; const soilTemperatures = historicalWeatherData.hourly.soil_temperature_0_to_7cm; temperatures.forEach((value, i) => { this.weatherData.push( new WeatherDataItem( value, times[i], humidities[i], windSpeeds[i], airPressures[i], windDirections[i], precipitations[i], rain[i], cloudcover[i], soilTemperatures[i] ) ); }); // 数据更新后触发懒加载,刷新表格 if (this.table) { this.table.onLazyLoad.emit({ first: 0, rows: 10, sortField: this.table.sortField, sortOrder: this.table.sortOrder, filters: this.table.filters }); } }, error: () => (this.showError = 'Something went wrong. Please try refreshing the page'), }); } // ...保留原有loadData、clearFilters、ngOnDestroy方法 }
3. WeatherService优化(可选)
若需要支持动态日期查询,可修改服务方法添加日期参数:
@Injectable({ providedIn: 'root', }) export class WeatherService { constructor(private http: HttpClient) {} getWeatherData( lat: string = '51.51', lon: string = '-0.13', startDate: string = '2005-08-25', endDate: string = '2005-08-25' ): Observable<WeatherData> { return this.http.get<WeatherData>( `https://archive-api.open-meteo.com/v1/era5?latitude=${lat}&longitude=${lon}&start_date=${startDate}&end_date=${endDate}&hourly=temperature_2m,relativehumidity_2m,dewpoint_2m,apparent_temperature,surface_pressure,precipitation,rain,cloudcover,windspeed_10m,winddirection_10m,soil_temperature_0_to_7cm` ); } }
关键说明
- 通过路由查询参数传递经纬度,适配跨路由组件的数据传递场景
- 监听
queryParamMap变化,支持组件复用(无需销毁重建即可切换城市) - 每次切换城市时清空旧数据,避免数据累加,同时触发表格懒加载更新视图
- 保留原有懒加载、过滤、排序功能,保证用户体验一致性
内容的提问来源于stack exchange,提问作者krk5570
相关产品推荐
相关产品推荐

