Angular 5中切换URL参数后如何按需重新渲染指定router-outlet?
我明白你现在的困扰——切换URL里的unit参数时,需要让头部、首页、页脚这些组件重新从服务器拉取数据,但用shouldReuseRoute = () => false全局禁用路由复用后,每次跳其他页面都会重复渲染头部和页脚,这显然不是你想要的。下面给你几个更精准的解决思路,不用大面积改写现有代码:
Angular的路由复用策略是可以自定义的,我们可以只在unit参数变化时,让对应的路由组件放弃复用、重新渲染,其他路由保持默认的复用逻辑。
步骤1:创建自定义复用策略类
新建一个custom-route-reuse-strategy.ts文件,继承默认的路由复用策略,重写shouldReuseRoute方法:
import { RouteReuseStrategy, ActivatedRouteSnapshot } from '@angular/router'; import { DefaultRouteReuseStrategy } from '@angular/router/src/router'; export class CustomRouteReuseStrategy extends DefaultRouteReuseStrategy { shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { // 判断当前路由和目标路由是否属于包含`:unit`的分支 const isUnitRelatedRoute = future.routeConfig?.path?.includes(':unit') || curr.routeConfig?.path?.includes(':unit'); if (isUnitRelatedRoute) { // 对比前后两次的`unit`参数,不同则不复用(重新渲染) const currentUnit = curr.paramMap.get('unit'); const futureUnit = future.paramMap.get('unit'); return currentUnit === futureUnit; } // 非unit相关路由,沿用默认的复用规则 return super.shouldReuseRoute(future, curr); } }
步骤2:在AppModule中注册这个策略
修改app.module.ts,把自定义策略注入到Angular的路由系统中:
import { NgModule } from '@angular/core'; import { RouteReuseStrategy } from '@angular/router'; import { CustomRouteReuseStrategy } from './custom-route-reuse-strategy'; @NgModule({ // ...其他模块配置 providers: [ { provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy } ] }) export class AppModule { }
这样设置后,只有当unit参数变化时,对应的路由组件才会重新触发ngOnInit、拉取新数据;跳转到其他不包含:unit的路由时,头部和页脚会正常复用,不会重复渲染。
如果你觉得自定义策略有点复杂,也可以选择对现有组件做少量修改——把ngOnInit里的HTTP请求抽成独立方法,然后订阅路由参数的变化来触发数据刷新:
比如在头部组件里修改:
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-header', templateUrl: './header.component.html' }) export class HeaderComponent implements OnInit { constructor(private route: ActivatedRoute) {} ngOnInit() { // 初始化加载数据 this.loadUnitData(); // 订阅unit参数变化,变化时重新加载 this.route.params.subscribe(params => { if (params['unit']) { this.loadUnitData(); } }); } // 把原来ngOnInit里的HTTP请求逻辑抽出来 private loadUnitData() { // 你的HTTP请求代码,比如: // this.http.get(`/api/data/${this.route.snapshot.paramMap.get('unit')}`).subscribe(...); } }
首页、页脚组件也做同样的修改。这个方案需要修改每个目标组件,但逻辑直观,适合组件数量不多的场景。
你也可以给包含:unit的路由添加Resolve守卫,在路由激活前就获取好新的unit对应数据,然后组件通过activatedRoute.data订阅数据变化。不过这个方案需要新增守卫类,同时组件也要调整数据获取的方式,工作量比方案2略大,这里就不展开细讲了。
内容的提问来源于stack exchange,提问作者Maksym Krugliachenko

