如何使用angular 2路由器重新加载当前路由

Pas*_*cal 103 angular

我正在使用带有哈希定位策略的角度2.

该组件加载了该路由:

"departments/:id/employees"
Run Code Online (Sandbox Code Playgroud)

到目前为止很好.

在我成功批量保存多个已编辑的表行后,我想通过以下方式重新加载当前路由URL:

this.router.navigate([`departments/${this.id}/employees`]);
Run Code Online (Sandbox Code Playgroud)

但没有任何反应,为什么?

Sim*_*ive 82

现在可以使用onSameUrlNavigationRouter config 的属性在Angular 5.1中完成此操作.

我添加了一个博客,解释了这里的内容,但其主旨如下

https://medium.com/engineering-on-the-incline/reloading-current-route-on-click-angular-5-1a1bfc740ab2

在路由器配置启用onSameUrlNavigation选项中,将其设置为'reload'.当您尝试导航到已经处于活动状态的路由时,这会导致路由器触发事件​​周期.

@ngModule({
 imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})],
 exports: [RouterModule],
 })
Run Code Online (Sandbox Code Playgroud)

在路径定义中,设置runGuardsAndResolversalways.这将告诉路由器始终启动警卫和解析器循环,触发相关事件.

export const routes: Routes = [
 {
   path: 'invites',
   component: InviteComponent,
   children: [
     {
       path: '',
       loadChildren: './pages/invites/invites.module#InvitesModule',
     },
   ],
   canActivate: [AuthenticationGuard],
   runGuardsAndResolvers: 'always',
 }
]
Run Code Online (Sandbox Code Playgroud)

最后,在要启用重新加载的每个组件中,您需要处理事件.这可以通过导入路由器,绑定到事件并调用重置方法来完成,该方法重置组件的状态并在需要时重新获取数据.

export class InviteComponent implements OnInit, OnDestroy {
 navigationSubscription;     

 constructor(
   // … your declarations here
   private router: Router,
 ) {
   // subscribe to the router events. Store the subscription so we can
   // unsubscribe later.
   this.navigationSubscription = this.router.events.subscribe((e: any) => {
     // If it is a NavigationEnd event re-initalise the component
     if (e instanceof NavigationEnd) {
       this.initialiseInvites();
     }
   });
 }

 initialiseInvites() {
   // Set default values and re-fetch any data you need.
 }

 ngOnDestroy() {
   if (this.navigationSubscription) {
     this.navigationSubscription.unsubscribe();
   }
 }
}
Run Code Online (Sandbox Code Playgroud)

完成所有这些步骤后,您应该启用路由重新加载.

  • 有没有办法重新加载组件而不是调用 `init` 函数, (2认同)

Arg*_*g0n 74

我在Angular的GitHub功能请求中找到了此解决方法:

this._router.routeReuseStrategy.shouldReuseRoute = function(){
    return false;
};

this._router.events.subscribe((evt) => {
    if (evt instanceof NavigationEnd) {
        this._router.navigated = false;
        window.scrollTo(0, 0);
    }
});
Run Code Online (Sandbox Code Playgroud)

我尝试将其添加到我的app.component.ts ngOnInit函数中,它确实有效.所有进一步点击同一链接现在重新加载component和数据.

链接到原始GitHub功能请求

幸得mihaicux2 GitHub上.

我在版本4.0.0-rc.3上测试了这个import { Router, NavigationEnd } from '@angular/router';

  • 非常糟糕的主意......因为一旦它应用了routeReuseStrategy.shouldReuseRoute = false,那么它就会加载组件层次结构的每个组件。所以这意味着您的每个父组件和子组件都会在任何 url 更改时开始重新加载。那么使用这个框架就没有意义了。 (3认同)
  • 这是一个非常糟糕的主意-现在您的ActivatedRoute将始终相同。 (2认同)
  • @AnandTyagi 如果您使用的是 Angular 5.1+,请尝试 SimonMcClives 解决方案。也许这对你更有效。 (2认同)

小智 60

在控制器中创建一个函数,重定向到预期的路由,如此

redirectTo(uri:string){
this.router.navigateByUrl('/DummyComponent', {skipLocationChange: true}).then(()=>
this.router.navigate([uri]));}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它

this.redirectTo('//place your uri here');
Run Code Online (Sandbox Code Playgroud)

此功能将重定向到虚拟路由并快速返回到目标路由,而无需用户意识到.

  • 当我使用''/'`而不是`'/ DummyComponent'时,它就像一个魅力 (10认同)
  • 在 Angular 7 中运行良好,浏览器历史记录中没有问题。由于针对特定组件,我选择使用此解决方案。在我看来,重新加载同一个页面通常是一种不正常的情况,所以让整个应用程序遵循特定的范式似乎有点过头了。这比其他解决方案更小且更容易实现。 (4认同)
  • 好的,它可以工作,但是......它将重新加载您的 HomeComponent (或您在路线“/”上的任何内容),将毫无意义地经历 ngOnInit/ngOnDestroy 的完整生命周期。最好有一个带有一些虚拟和轻量级组件的特定路线,否则你会注意到滞后 (3认同)
  • 谢谢!最佳解决方案. (2认同)
  • 这是最好的答案。我最终制作了一个 /dummy 组件并为其添加了一条路线,然后一切都在 Angular 10 上完美运行。 (2认同)

And*_*ris 51

我将这个用于 Angular 11 项目:

reloadCurrentRoute() {
    const currentUrl = this.router.url;
    this.router.navigateByUrl('/', {skipLocationChange: true}).then(() => {
        this.router.navigate([currentUrl]);
    });
}
Run Code Online (Sandbox Code Playgroud)

PS:已测试并适用于 7 以上的所有版本。

  • 我想我应该谈谈我使用这个解决方案的经验。对我来说,它似乎重新加载与路线相关的整个组件。在我的情况下,具有不同路由参数的常规 router.navigate 将保持组件加载并仅加载 ngOnInit 中的新更改(基于路由参数)。您的解决方案似乎没有这样做,它似乎实际上重新加载整个组件,然后根据路由参数在 ngOnInit 中进行更改。无论如何,就我的情况而言,这对我来说是一个小小的不便,而您的解决方案可以满足我的需求。 (2认同)

Yak*_*ain 34

如果您的navigate()不会更改已在浏览器地址栏上显示的URL,则路由器无需执行任何操作.刷新数据不是路由器的工作.如果要刷新数据,请创建注入组件的服务并调用服务上的加载功能.如果将检索新数据,它将通过绑定更新视图.

  • 我不同意如果你想重新运行警卫,如果有人退出了吗? (69认同)
  • @YakovFain抱歉,但这是错误的。这意味着您现在对路线行为有了两个事实来源-一个发生在警卫队期间,另一个发生在组件中。现在,您不仅有可能会复制逻辑,而且还反对更自然的数据流:1.更改API,2.刷新路由以从API获取数据的新状态,从而使API成为真理。根本没有理由不给予用户手动重新触发路由的能力,以使自然的数据流可以再次发生。 (8认同)
  • 现在你说它我必须同意但是... angularjs ui路由器有一个重载选项,因此重新加载路线被注意到了;-)但是,我可以只为该提示重新加载数据thx这实际上是显而易见的... (2认同)
  • 重新运行解析器,守卫等如何? (2认同)
  • 我认为这不是一个好答案。路由器应该是您数据真实性的来源。如果您必须通过单独的服务重新加载它,则路由器将不再了解最新版本,并且您的组件也将不再依赖路由器作为事实来源。 (2认同)
  • 如果您有多个通往同一组件的路由,则此解决方案也会出现问题。当路线最终转到同一组件时更改路线不会重新加载。 (2认同)

new*_*ari 28

有点棘手:使用相同的路径与一些虚拟参数.例如-

refresh(){
  this.router.navigate(["/same/route/path?refresh=1"]);
}
Run Code Online (Sandbox Code Playgroud)

  • 现在:`this.router.navigate(['/ pocetna'],{queryParams:{'refresh':1}});`和`route.queryParams.subscribe(val => myRefreshMethod())`其中`route: ActivatedRoute`注入刷新组件...希望它有所帮助 (11认同)
  • 可能有点丑吧 (3认同)
  • 目前在Angular 7中,这似乎不再起作用。任何人都可以确认,或者我做错了什么?(我也尝试过insan-e的细微变化。) (2认同)

Wla*_*ada 28

这就是我对Angular 9所做的。我不确定这在旧版本中是否有效。

当您需要重新加载时,您将需要调用它。

 this.router.navigate([], {
    skipLocationChange: true,
    queryParamsHandling: 'merge' //== if you need to keep queryParams
  })
Run Code Online (Sandbox Code Playgroud)

路由器 forRoot 需要将 SameUrlNavigation 设置为“重新加载”

 RouterModule.forRoot(appRoutes, {
  // ..
  onSameUrlNavigation: 'reload',
  // ..
})
Run Code Online (Sandbox Code Playgroud)

并且您的每条路线都需要将 runGuardsAndResolvers 设置为“始终”

{
    path: '',
    data: {},
    runGuardsAndResolvers: 'always'
},
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案。“onSameUrlNavigation”自 Angular 5 起生效。请投票将其移至顶部 (4认同)
  • 我的问题通过最后一段代码解决了。设置 runGuardsAndResolvers: 'always' 强制应用程序使用防护,因此重复调用那里存在的 API。谢谢你@Wlada (2认同)

ind*_*eed 16

Angular 2-4路由重装黑客

对我来说,在根组件(组件,存在于任何路由上)中使用此方法可以:

onRefresh() {
  this.router.routeReuseStrategy.shouldReuseRoute = function(){return false;};

  let currentUrl = this.router.url + '?';

  this.router.navigateByUrl(currentUrl)
    .then(() => {
      this.router.navigated = false;
      this.router.navigate([this.router.url]);
    });
  }
Run Code Online (Sandbox Code Playgroud)


Nit*_*ate 9

这对我来说就像魅力

this.router.navigateByUrl('/', {skipLocationChange: true}).then(()=>
this.router.navigate([<route>]));
Run Code Online (Sandbox Code Playgroud)

  • 这是最简单的答案。如果可以的话,我会将其标记为已接受的答案。与公认的答案相反,在某些情况下,您可能需要重新加载页面上使用的每个组件,并且必须单独重新加载每个组件,这些组件可能位于不同的路线上,即使通过服务也是过大的。 (3认同)

kar*_*thi 8

在参数更改上,不会发生重新加载页面。这确实是个好功能。无需重新加载页面,但我们应该更改组件的值。paramChange方法将调用URL更改。这样我们就可以更新组件数据

/product/: id / details

import { ActivatedRoute, Params, Router } from ‘@angular/router’;

export class ProductDetailsComponent implements OnInit {

constructor(private route: ActivatedRoute, private router: Router) {
    this.route.params.subscribe(params => {
        this.paramsChange(params.id);
    });
}

// Call this method on page change

ngOnInit() {

}

// Call this method on change of the param
paramsChange(id) {

}
Run Code Online (Sandbox Code Playgroud)


Car*_*eli 5

找到了一个快速而直接的解决方案,不需要修补角度的内部工作:

基本上:只需创建一个具有相同目标模块的备用路由,然后在它们之间切换:

const routes: Routes = [
  {
    path: 'gesuch',
    loadChildren: './sections/gesuch/gesuch.module#GesuchModule'
  },
  {
    path: 'gesuch-neu',
    loadChildren: './sections/gesuch/gesuch.module#GesuchModule'
  }
];
Run Code Online (Sandbox Code Playgroud)

这里的toggeling菜单:

<ul class="navigation">
    <li routerLink="/gesuch-neu" *ngIf="'gesuch' === getSection()">Gesuch</li>
    <li routerLink="/gesuch" *ngIf="'gesuch' !== getSection()">Gesuch</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你 :)


Vla*_*lad 5

对我来说可以硬编码

this.router.routeReuseStrategy.shouldReuseRoute = function() {
    return false;
    // or
    return true;
};
Run Code Online (Sandbox Code Playgroud)

  • 不建议!人们在整个 SO 中不断以不同的方式重新发布这个解决方案。是的,它可能会解决您眼前的问题,但您稍后会忘记您实现了此功能,并且您将花费数小时试图找出您的应用程序出现奇怪行为的原因。 (5认同)

Evg*_*rev 5

解决方案:

订阅 URL 参数并在那里初始化组件。没有技巧,只是“新 URL --> 新数据”,包括第一次加载。

对于 URL 参数(如/persons/:id):

constructor(protected activeRoute: ActivatedRoute, ...) {
    this.activeRoute.paramMap.subscribe(paramMap => {
        const id = paramMap.get('id');    // get param from dictonary
        this.load(id);                    // load your data
    });
}
Run Code Online (Sandbox Code Playgroud)

对于 URL 查询参数(如?q=...&returnUrl=...)(通常不需要):

    this.activeRoute.queryParamMap.subscribe(queryParamMap => {
        const returnUrl = queryParamMap.get('returnUrl');
        ...
    });
Run Code Online (Sandbox Code Playgroud)

问题的原因是:

当 URL 更改时,Angular 将尽可能重用旧组件以节省计算机资源。数据加载是您的自定义代码,因此 Angular 无法为您完成此操作。