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

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

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

"departments/:id/employees"

到目前为止还好。

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

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

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

496707 次浏览

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

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

reloadPage() {
window.location.reload();
}
< p >小技巧: 使用相同的路径和一些虚拟参数。例如,< / p >
refresh(){
this.router.navigate(["/same/route/path?refresh=1"]);
}

编辑

对于较新版本的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函数中,它确实工作了。所有对同一链接的进一步点击现在重新加载component和data。

原始GitHub特性请求链接 .

功劳归于GitHub上的mihaicux2

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

这招对我很管用:

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

重新加载角2中的当前路由非常有用的链接重载当前路由在angualr 2或4

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

  1. 使用虚拟查询参数
  2. 使用虚拟路由

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

试试这个

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

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

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

请看一个例子:

export class Component implements OnInit {


constructor() {   }


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


ngOnInit () {


}

假设你想要刷新的组件路由是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"后的确切路线。

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

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

通过使用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 {}

要使用这个,我们只需要在我们想要去的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导航上发出路由器事件。< / p >

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

不动路由器

  • 传递一个刷新queryParam,在URL和 订阅路由组件中的queryParams。李< / >
  • 使用router-outlet的activate Event来获取一个

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

希望这能有所帮助。

我正在使用setTimeoutnavigationByUrl来解决这个问题…这对我来说很有效。

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

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

如果你通过路由器连接改变路径,遵循以下命令:

  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+中(原生地)解决了;检查

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

如果你想要针对单个组件,如下所示: 使用一个可以改变的查询参数,这样你就可以随心所欲地浏览很多次

在导航点(类)

   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。否则使用正常的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));
}
}

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

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

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

@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,然后到实际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。

这就是我对角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) }]);
< h1 id = " solution-tdbp " >解决方案:< / h1 >

订阅URL参数并在那里初始化组件。没有技巧, just "新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,
},
});