我使用的是带有hashlocation策略的angular 2。

组件是用这个路由加载的:

"departments/:id/employees"

到目前为止还好。

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

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

但是什么都没有发生,为什么?


如果你的navigate()没有改变浏览器地址栏上已经显示的URL,路由器就不需要做什么。刷新数据不是路由器的工作。如果希望刷新数据,可以创建一个注入到组件中的服务,并调用该服务上的加载函数。如果将检索新数据,它将通过绑定更新视图。


只需使用本地javascript重载方法:

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

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

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

EDIT

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

旧的答案

我在一个针对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);
    }
});

我试着把它添加到我的app.component.ts ngOnInit函数中,它确实工作了。现在,在同一链接上的所有进一步单击都将重新加载组件和数据。

链接到原始GitHub功能请求

感谢GitHub上的mihaicux2。

我在4.0.0-rc版本上进行了测试。导入{Router, NavigationEnd} from '@angular/ Router ';


这招对我很管用:

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

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

找到了一个快速而直接的解决方案,不需要修补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>

希望能有所帮助。


在我的例子中:

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

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

正确的工作


对我来说是硬编码

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

这现在可以在Angular 5.1中使用Router配置中的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();
   }
 }
}

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


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

重载当前路由在angular 2非常有用的链接重载当前路由在angualr 2或4

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

使用虚拟查询参数 使用虚拟路由

欲了解更多信息,请参见上面的链接


试试这个

窗口。打开(“仪表板”、“_self ');

它的老方法,但适用于所有的角版本,它重定向路由和刷新页面。


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

请看一个例子:

export class Component implements OnInit {

  constructor() {   }

  refresh() {
    this.router.navigate(['same-route-here']);
    this.ngOnInit();   }

  ngOnInit () {

  }

假设你想要刷新的组件的路由是视图,然后使用这个:

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

你可以在方法中添加一个调试器,以了解导航到“departments/:id/employees”后的确切路径。


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

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

然后像这样使用它

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

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


订阅路由参数更改

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

通过使用一个虚拟组件和重新加载的路由解决了一个类似的场景,这实际上是一个重定向。这当然不能涵盖所有的用户场景,但只适用于我的场景。

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 {}

要使用这个,我们只需要在我们想要去的url中添加reload:

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

在参数更改时,重新加载页面将不会发生。这是一个很好的特性。不需要重新加载页面,但我们应该改变组件的值。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) {

}

这对我来说很管用

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

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

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

有点硬核,但是

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

    this.router.onSameUrlNavigation = 'ignore';

});

有不同的方法来刷新当前路由

改变路由器的行为(从Angular 5.1开始) 设置路由器onSameUrlNavigation为“reload”。这将在相同的URL导航上发出路由器事件。

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

不动路由器

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

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

希望这能有所帮助。


我使用setTimeout和navigationByUrl来解决这个问题…这对我来说很有效。

它被重定向到其他URL,而不是再次出现在当前URL…

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

如果你通过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;
             }
          })
      }

下面的代码将工作:

logoFn(url: any) {

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

}

我相信这个问题已经在Angular 6+中(原生地)解决了;检查

这里https://github.com/angular/angular/issues/13831 && 在这里https://medium.com/engineering-on-the-incline/reloading-current-route-on-click-angular-5-1a1bfc740ab2

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

如果你想要针对单个组件,以下是方法: 使用可更改的查询参数,以便您可以任意多次导航。

在导航点(类)

   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似乎仍然没有提供一个好的解决方案。我在这里提出了一个github问题:https://github.com/angular/angular/issues/31843

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

注意:只有在需要重载功能的情况下才使用ReloadRouter。否则使用普通路由器。

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

我在Angular 11项目中使用这个:

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

PS:测试和工作在所有版本以上7。


从@angular/ Router中导入Router和ActivatedRoute

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

注入Router和ActivatedRoute(以防你需要URL中的任何东西)

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

从URL中获取所需的任何参数。

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

使用一个技巧,通过导航到一个虚拟url或主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 12中所做的。我不确定这是否适用于9以下的版本。

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

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

Router forRoot需要将SameUrlNavigation设置为“reload”

 RouterModule.forRoot(appRoutes, {
  // ..
  onSameUrlNavigation: 'reload',
  // ..
})

你的每个路径都需要将runGuardsAndResolvers设置为always

{
    path: '',
    data: {},
    runGuardsAndResolvers: 'always'
},

决定何时存储路由返回false

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

并将router的导航值设置为false,表示该路由从未被路由

this.mySubscription = this.router.events.subscribe(event => {
    if (event instanceof NavigationEnd) {
        this.router.navigated = false;
    }
});

我尝试了一些修复方法,但没有一个有效。我的版本很简单:在查询参数中添加一个新的未使用的参数

            if (force) {
                let key = 'time';

                while (key in filter) {
                    key = '_' + key;
                }

                filter[key] = Date.now();
            }

            this.router.navigate(['.', { filter: JSON.stringify(filter) }]);

解决方案:

订阅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
    });
}

对于URL查询参数(比如?q=…&returnUrl=…)(通常不是必需的):

    this.activeRoute.queryParamMap.subscribe(queryParamMap => {
        const returnUrl = queryParamMap.get('returnUrl');
        ...
    });

问题的原因是:

当URL发生变化时,Angular会尽可能重用旧的组件,以节省计算机资源。加载数据是你的自定义代码,所以Angular不能为你做这件事。


另一种选择是使用纯js,但页面实际上会刷新。

window.location.reload(true)

写一个函数。, reloadCurrentPage。由于window是一个全局对象,可以直接在Angular组件中重用,window.location.reload()会重新加载当前活动的页面。

function reloadCurrentPage() {
    window.location.reload();
}

使用“时间戳”是一种廉价而神奇的方法。

this.router.navigate([], {
    relativeTo: this.route,
    queryParams: {
        ...this.route.snapshot.queryParams,
        // replace 't' with any others not to conflict with exsiting
        // '2^11' prevents reloading in about 2 seconds
        t: Date.now() >> 11, 
        skipLocationChange: true,
    },
});