【问题标题】:How to reload the current route with the angular 2 router如何使用 Angular 2 路由器重新加载当前路由
【发布时间】:2017-04-20 08:46:28
【问题描述】:

我正在使用 angular 2 和 hashlocation 策略。

组件使用该路由加载:

"departments/:id/employees"

到目前为止还不错。

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

this.router.navigate([`departments/${this.id}/employees`]);

但是什么也没发生,为什么?

【问题讨论】:

标签: angular typescript


【解决方案1】:

如果您的 navigate() 没有更改浏览器地址栏上已经显示的 URL,则路由器与此无关。刷新数据不是路由器的工作。如果要刷新数据,请创建一个注入到组件中的服务并在该服务上调用加载函数。如果要检索新数据,它将通过绑定更新视图。

【讨论】:

  • 现在你说我必须同意但是...... angularjs ui 路由器有一个重新加载选项,因此重新加载路由是有意见的 ;-) 但是是的,我可以为那个提示做一个重新加载数据谢谢其实很明显……
  • 我不同意如果你想重新运行守卫,如果有人注销的话?
  • @YakovFain 抱歉,但这是错误的。这意味着您现在有两个路由行为的真实来源 - 一个发生在警卫期间,另一个发生在组件中。您现在不仅可能会重复逻辑,而且还与更自然的数据流背道而驰:1. 更改 API,2. 刷新路由以从 API 获取新的数据状态,使 API 成为事实来源。根本没有理由不让用户手动重新触发路由,以便数据的自然流动可以再次发生。
  • 我认为这不是一个好的答案。路由器应该是您数据的真实来源。如果您必须通过单独的服务重新加载它,那么路由器将不再知道最新版本,并且您的组件将不再依赖您的路由器作为事实来源。
  • 如果你有多个路由到同一个组件,这个解决方案也会有问题。当路由最终转到相同的组件时更改路由不会重新加载。
【解决方案2】:

只需使用原生 javascript 重新加载方法:

reloadPage() {
    window.location.reload();
}

【讨论】:

  • 这将重新加载整个应用程序,导致您丢失会话中存储的任何内容,例如用户信息、范围数据等
  • 不在会话中,但在内存中。会话数据应使用 sessionStorage API 存储。
  • 我的登录页面导航必须使用这个... angular 应用程序在没有从服务器获取状态的情况下被初始化(因为没有记录)...
【解决方案3】:

小技巧: 对一些虚拟参数使用相同的路径。例如-

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

【讨论】:

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

编辑

对于较新版本的 Angular (5.1+),请使用 @Simon McClive 建议的答案

旧答案

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

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

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

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

Link to original GitHub feature request

感谢 GitHub 上的 mihaicux2

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

【讨论】:

  • 刚刚在 Angular 4.4.x 中尝试过,这完全有效。谢谢!
  • 这对我来说非常有用,直到我实现了 Material 的 nav-tab-bar 来在我的应用程序中导航每个父路由的子路由。一旦用户点击运行此代码的页面,动画墨水条就会消失。 (为什么?我没有足够的时间或空间来解释......)
  • 这是一个非常糟糕的主意——你的 ActivatedRoute 现在总是一样的。
  • @AnandTyagi 如果您使用的是 Angular 5.1+,请尝试 SimonMcClives 解决方案。也许这对你更有效。
  • 非常糟糕的主意...因为一旦它应用了 routeReuseStrategy.shouldReuseRoute = false,那么它将加载组件层次结构的每个组件。因此,这意味着您的每个父子组件都会在任何 url 更改时开始重新加载。那么使用这个框架就没有意义了。
【解决方案5】:

这对我有用:

let url = `departments/${this.id}/employees`;

this.router.navigated = false;
this.router.navigateByUrl(url);

【讨论】:

  • 刚刚在最新版本的 Angular 4 中尝试过,但它不再有效。
【解决方案6】:

找到了一个快速直接的解决方案,不需要修改 angular 的内部工作原理:

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

const routes: Routes = [
  {
    path: 'gesuch',
    loadChildren: './sections/gesuch/gesuch.module#GesuchModule'
  },
  {
    path: 'gesuch-neu',
    loadChildren: './sections/gesuch/gesuch.module#GesuchModule'
  }
];

这里是切换菜单:

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

希望对你有帮助:)

【讨论】:

  • 如果备用路由有参数,你想在参数变化时重新加载?
【解决方案7】:

就我而言:

const navigationExtras: NavigationExtras = {
    queryParams: { 'param': val }
};

this.router.navigate([], navigationExtras);

工作正确

【讨论】:

    【解决方案8】:

    对我来说,使用硬编码工作

    this.router.routeReuseStrategy.shouldReuseRoute = function() {
        return false;
        // or
        return true;
    };
    

    【讨论】:

    • 不推荐!人们在整个 SO 中不断以不同的方式重新发布此解决方案。是的,它可能会解决您当前的问题,但您稍后会忘记您已实现此功能,并且您将花费数小时试图找出您的应用出现奇怪行为的原因。
    • 如果你必须使用这个使用 Ebraheem Alrabee 的解决方案,并且只将它应用到一个单一的路线。
    【解决方案9】:

    现在可以在 Angular 5.1 中使用路由器配置的 onSameUrlNavigation 属性来完成。

    我已经添加了一个博客来解释这里的方法,但它的要点如下

    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],
     })
    

    在您的路由定义中,将runGuardsAndResolvers 设置为always。这将告诉路由器始终启动守卫和解析器循环,触发相关事件。

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

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

    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();
       }
     }
    }
    

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

    【讨论】:

    • 有没有办法重新加载组件而不是调用init函数,
    • 我不这么认为...除非您导航离开该路线并再次返回。初始化函数并不是世界末日,您可以控制初始化,使其与重新加载组件具有相同的效果。您是否有任何特殊原因想要在没有init 的情况下进行完全重新加载?
    • 我已经找到了解决我的问题的方法,感谢您的回复和有用的博客。
    • 如何在 Angular 4 中执行此操作,而不是重新加载窗口。
    • 非常适合我的 Angular5 应用程序!在 ngOnDestroy() 中取消订阅有点重要 - 当你不这样做时会很有趣:-)
    【解决方案10】:

    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]);
        });
      }
    

    【讨论】:

    • 谨慎使用这种方法,这将全局影响路由器行为(在子路由之间导航时,父路由总是会重新加载)。
    【解决方案11】:

    reload current route in angular 2 非常有用的链接,用于在 angualr 2 或 4 中重新加载当前路线

    在此定义了两种技术来做到这一点

    1. 带有虚拟查询参数
    2. 带有虚拟路由

    更多内容见以上链接

    【讨论】:

      【解决方案12】:

      试试这个

      window.open('dashboard', '_self');

      它的旧方法,但适用于所有角度版本,它在路由上重定向并刷新页面。

      【讨论】:

        【解决方案13】:

        实现 OnInit 并在 route.navigate() 方法中调用 ngOnInit()

        看一个例子:

        export class Component implements OnInit {
        
          constructor() {   }
        
          refresh() {
            this.router.navigate(['same-route-here']);
            this.ngOnInit();   }
        
          ngOnInit () {
        
          }
        

        【讨论】:

          【解决方案14】:

          假设你要刷新的组件的路由是view,那么使用这个:

          this.router.routeReuseStrategy.shouldReuseRoute = function (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) {
            if (future.url.toString() === 'view' && curr.url.toString() === future.url.toString()) {
              return false;
            }
            return (future.routeConfig === curr.routeConfig);
          }; 
          

          您可以在方法中添加debugger 以了解导航到"departments/:id/employees" 后的确切路线。

          【讨论】:

            【解决方案15】:

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

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

            然后像这样使用它

            this.redirectTo('//place your uri here');
            

            此函数将重定向到一个虚拟路由并在用户没有意识到的情况下快速返回到目标路由。

            【讨论】:

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

            订阅路由参数变化

                // parent param listener ie: "/:id"
                this.route.params.subscribe(params => {
                    // do something on parent param change
                    let parent_id = params['id']; // set slug
                });
            
                // child param listener ie: "/:id/:id"
                this.route.firstChild.params.subscribe(params => {
                    // do something on child param change
                    let child_id = params['id'];
                });
            

            【讨论】:

              【解决方案17】:

              通过使用reload 的虚拟组件和路由解决了类似的情况,它实际上执行了redirect。这绝对不涵盖所有用户场景,但仅适用于我的场景。

              import { Component, OnInit } from '@angular/core';
              import { Router, ActivatedRoute } from '@angular/router';
              import { Http } from '@angular/http';
              
              @Component({
                selector: 'reload',
                template: `
                  <h1>Reloading...</h1>
                `,
              })
              export class ReloadComponent implements OnInit{
                constructor(private router: Router, private route: ActivatedRoute) {
                }
              
                ngOnInit() {
                  const url = this.route.snapshot.pathFromRoot.pop().url.map(u => u.path).join('/');
                  this.router.navigateByUrl(url);
                }
              }
              

              路由使用通配符来捕获所有 url:

              import { RouterModule } from '@angular/router';
              import { NgModule } from '@angular/core';
              import { LoginViewComponent } from './views/login/login.component';
              import { HomeViewComponent } from './views/home/home.component';
              import { ReloadComponent } from './views/reload/reload.component';
              
              @NgModule({
                declarations: [ 
                  LoginViewComponent, HomeViewComponent, ReloadComponent
                ],
                imports: [
                  RouterModule.forRoot([
                    { path: 'login', component: LoginViewComponent },
                    { path: 'home', component: HomeViewComponent },
                    { 
                      path: 'reload',
                      children: [{
                        path: '**',
                        component: ReloadComponent 
                      }]
                    },
                    { path: '**', redirectTo: 'login'}
                  ])
                ],
                exports: [
                  RouterModule,
                ],
                providers: [],
              
              })
              export class AppRoutingModule {}
              

              要使用它,我们只需要将 reload 添加到我们想要去的 url:

                this.router.navigateByUrl('reload/some/route/again/fresh', {skipLocationChange: true})
              

              【讨论】:

                【解决方案18】:

                参数更改重新加载页面不会发生。这真是一个很好的功能。无需重新加载页面,但我们应该更改组件的值。 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) {
                
                }
                

                【讨论】:

                  【解决方案19】:

                  这对我来说就像一个魅力

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

                  【讨论】:

                  • 这是最简单的答案。如果可以的话,我会将其标记为已接受的答案。与公认的答案相反,在某些情况下,您可能需要重新加载页面上使用的每个组件,并且必须单独重新加载每个组件,这些组件可能位于不同的路径,即使通过服务也是过大的。
                  • 似乎对我不起作用。我期待这会再次重新触发 ngOnInit 函数。显然它没有......或者我错过了什么?
                  • ngOnInit 功能不会被触发,如果你已经在同一条路线。如果您需要调用它,您可以手动调用它作为上述代码的第三行。
                  【解决方案20】:

                  一种解决方案是传递一个虚拟参数(即以秒为单位的时间),这样链接总是会重新加载:

                  this.router.navigate(["/url", {myRealData: RealData, dummyData: (new Date).getTime()}])
                  

                  【讨论】:

                    【解决方案21】:

                    有点硬核但是

                    this.router.onSameUrlNavigation = 'reload';
                    this.router.navigateByUrl(this.router.url).then(() => {
                    
                        this.router.onSameUrlNavigation = 'ignore';
                    
                    });
                    

                    【讨论】:

                      【解决方案22】:

                      刷新当前路线有不同的方法

                      更改路由器行为(自 Angular 5.1 起) 将路由器 onSameUrlNavigation 设置为“重新加载”。这将在相同的 URL 导航上发出路由器事件。

                      • 然后您可以通过订阅路由来处理它们
                      • 您可以将它与 runGuardsAndResolvers 组合使用以重新运行解析器

                      不要碰路由器

                      • 使用 URL 中的当前时间戳传递刷新 queryParam 和 在路由组件中订阅 queryParams。
                      • 使用路由器出口的激活事件获取 持有路由组件。

                      我在https://medium.com/@kevinkreuzer/refresh-current-route-in-angular-512a19d58f6e下写了更详细的解释

                      希望这会有所帮助。

                      【讨论】:

                        【解决方案23】:

                        我正在使用setTimeoutnavigationByUrl 来解决这个问题......而且它对我来说很好用。

                        它被重定向到其他 URL 并再次出现在当前 URL...

                         setTimeout(() => {
                             this.router.navigateByUrl('/dashboard', {skipLocationChange: false}).then(() =>
                                   this.router.navigate([route]));
                             }, 500)
                        

                        【讨论】:

                          【解决方案24】:

                          如果您通过 Router Link 更改路线,请按照以下步骤操作:

                            constructor(public routerNavigate: Router){
                          
                                   this.router.routeReuseStrategy.shouldReuseRoute = function () {
                                      return false;
                                    };
                          
                                    this.router.events.subscribe((evt) => {
                          
                                      if (evt instanceof NavigationEnd) {
                          
                                          this.router.navigated = false;
                                       }
                                    })
                                }
                          

                          【讨论】:

                            【解决方案25】:

                            以下代码将起作用:

                            logoFn(url: any) {
                            
                                this.router.routeReuseStrategy.shouldReuseRoute = function () {
                                    return false;
                                };
                                this.router.navigate(['']); or
                                this.router.navigate([url]);
                            
                            }
                            

                            【讨论】:

                              【解决方案26】:

                              我相信这已经在 Angular 6+ 中(本地)解决了;检查

                              但这适用于整个路线(也包括所有子路线)

                              如果您想定位单个组件,方法如下: 使用可更改的查询参数,这样您就可以根据需要进行多次导航。

                              在导航点(类)

                                 this.router.navigate(['/route'], {
                                      queryParams: { 'refresh': Date.now() }
                                  });
                              

                              在您要“刷新/重新加载”的组件中

                              // . . . Component Class Body
                              
                                $_route$: Subscription;
                                constructor (private _route: ActivatedRoute) {}
                              
                                ngOnInit() {
                                  this.$_route$ = this._route.queryParams.subscribe(params => {
                                    if (params['refresh']) {
                                       // Do Something
                                       // Could be calling this.ngOnInit() PS: I Strongly advise against this
                                    }
                              
                                  });
                                }
                              
                                ngOnDestroy() {
                                  // Always unsubscribe to prevent memory leak and unexpected behavior
                                  this.$_route$.unsubscribe();
                                }
                              
                              // . . . End of Component Class Body
                              

                              【讨论】:

                              • 有趣的是,这种方法只能工作一次 - Angular 中似乎有一个错误,queryParamsMap 主题只在第一次更新,但在任何后续更新中都没有.
                              【解决方案27】:

                              据我所知,Angular 2 中的路由器无法做到这一点。但你可以这样做:

                              window.location.href = window.location.href
                              

                              重新加载视图。

                              【讨论】:

                              • 这会刷新整个应用程序,而不仅仅是当前路由!
                              • @HelloWorld - 在哪里把逻辑放在角度 7 中?
                              • 角度版本无关紧要——这只是普通的 js 代码
                              • 把这个放在点击功能上。 window.location.href = '/' 或 '/login' 在 app-routing.module.ts 中定义。在我的情况下,当用户注销时,它应该返回登录屏幕,所以在注销时我会清除所有身份验证数据,并在成功使用 window.location.href = '/' 时。这意味着重新加载登录页面并再次重新运行所有 javascript。对于路线的正常更改,我不建议在不需要重新运行功能的情况下这样做。
                              • 我相信这可能会完全重置您的 NgRx 存储 - 因此您已经获取的任何数据都会丢失。
                              【解决方案28】:

                              非常令人沮丧的是,Angular 仍然 似乎没有为此提供一个好的解决方案。我在这里提出了一个 github 问题:https://github.com/angular/angular/issues/31843

                              与此同时,这是我的解决方法。它建立在上面建议的其他一些解决方案之上,但我认为它更强大一些。它涉及将路由器服务包装在“ReloadRouter”中,该服务负责重新加载功能,并将RELOAD_PLACEHOLDER 添加到核心路由器配置中。这用于临时导航并避免触发任何其他路线(或守卫)。

                              注意:仅在您想要重新加载功能的情况下使用ReloadRouter。否则使用普通的Router

                              import { Injectable } from '@angular/core';
                              import { NavigationExtras, Router } from '@angular/router';
                              
                              @Injectable({
                                providedIn: 'root'
                              })
                              export class ReloadRouter {
                                constructor(public readonly router: Router) {
                                  router.config.unshift({ path: 'RELOAD_PLACEHOLDER' });
                                }
                              
                                public navigate(commands: any[], extras?: NavigationExtras): Promise<boolean> {
                                  return this.router
                                    .navigateByUrl('/RELOAD_PLACEHOLDER', {skipLocationChange: true})
                                    .then(() => this.router.navigate(commands, extras));
                                }
                              }
                              

                              【讨论】:

                                【解决方案29】:

                                我将这个用于 Angular 11 项目:

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

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

                                【讨论】:

                                • 我想我会谈谈我对这个解决方案的经验。对我来说,它似乎重新加载了与路由关联的整个组件。在我的情况下,具有不同路由参数的常规 router.navigate 将保持组件加载并仅从 ngOnInit 加载新更改(基于路由参数)。您的解决方案似乎没有这样做,它似乎实际上重新加载了整个组件,然后根据路由参数在 ngOnInit 中对其进行更改。无论如何,在我的情况下,这对我来说是一个小小的不便,您的解决方案可以满足我的需求。
                                • 最佳答案 +1
                                • 这似乎对我不起作用。我的情况是我想在离开应用程序状态时重新加载,所以我将其包裹在 if 中以检查应用程序的先前状态。如果这是真的,我们处于“其他”状态但不再存在,则状态标志被重置并且此代码运行,但没有任何反应。我用过window.location.reload();,但这似乎是一种更暴力的方法。此线程中的其他建议均未奏效。
                                【解决方案30】:

                                @angular/router 导入RouterActivatedRoute

                                import { ActivatedRoute, Router } from '@angular/router';
                                

                                注入RouterActivatedRoute(以防你需要来自 URL 的任何内容)

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

                                如果需要,从 URL 获取任何参数。

                                const appointmentId = this.route.snapshot.paramMap.get('appointmentIdentifier');
                                

                                通过导航到虚拟或主 url 然后到实际 url 来使用技巧将刷新组件。

                                this.router.navigateByUrl('/appointments', { skipLocationChange: true }).then(() => {
                                    this.router.navigate([`appointment/${appointmentId}`])
                                });
                                

                                你的情况

                                const id= this.route.snapshot.paramMap.get('id');
                                this.router.navigateByUrl('/departments', { skipLocationChange: true }).then(() => {
                                    this.router.navigate([`departments/${id}/employees`]);
                                });
                                

                                如果您使用虚拟路由,如果您已实现未找到的 url,以防与任何 url 不匹配,您将看到标题闪烁“未找到”。

                                【讨论】:

                                • 先生,你是谁,在 Angular 方面如此聪明
                                猜你喜欢
                                • 2019-08-26
                                • 2017-09-19
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2018-03-20
                                • 2014-02-24
                                • 2017-07-27
                                • 2016-09-09
                                相关资源
                                最近更新 更多