我正在使用 angular 2 和 hashlocation
策略。
组件使用该路由加载:
"departments/:id/employees"
到目前为止还好。
在我成功批量保存多个已编辑的表行后,我想通过以下方式重新加载当前路由 URL:
this.router.navigate([`departments/${this.id}/employees`]);
但是什么都没有发生,为什么?
在控制器中创建一个函数,像这样重定向到预期的路由
redirectTo(uri:string){
this.router.navigateByUrl('/', {skipLocationChange: true}).then(()=>
this.router.navigate([uri]));
}
然后像这样使用它
this.redirectTo('//place your uri here');
这个函数将重定向到一个虚拟路由并在用户没有意识到的情况下快速返回到目标路由。
现在可以使用路由器配置的 onSameUrlNavigation
属性在 Angular 5.1 中完成此操作。
我添加了一个博客来解释这里的方法,但它的要点如下
在您的路由器配置中启用 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 11 项目:
reloadCurrentRoute() {
const currentUrl = this.router.url;
this.router.navigateByUrl('/', {skipLocationChange: true}).then(() => {
this.router.navigate([currentUrl]);
});
}
PS:经过测试并适用于 7 以上的所有版本。
if
中以检查应用程序的先前状态。如果这是真的,我们处于“其他”状态但不再存在,则状态标志被重置并且此代码运行,但没有任何反应。我使用了 window.location.reload();
,但这似乎是一种更暴力的方法。该线程中的其他建议均未奏效。
编辑
对于较新版本的 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
和数据。
Link to original GitHub feature request
归功于 GitHub 上的 mihaicux2。
我用 import { Router, NavigationEnd } from '@angular/router';
在版本 4.0.0-rc.3
上测试了这个
如果您的 navigate() 没有更改浏览器地址栏上已经显示的 URL,则路由器无关。刷新数据不是路由器的工作。如果要刷新数据,请创建一个注入到组件中的服务并在该服务上调用加载函数。如果要检索新数据,它将通过绑定更新视图。
这就是我对 Angular 9 所做的。我不确定这是否适用于旧版本。
当您需要重新加载时,您需要调用它。
this.router.navigate([], {
skipLocationChange: true,
queryParamsHandling: 'merge' //== if you need to keep queryParams
})
路由器 forRoot 需要将 SameUrlNavigation 设置为“重新加载”
RouterModule.forRoot(appRoutes, {
// ..
onSameUrlNavigation: 'reload',
// ..
})
而且您的每条路线都需要将 runGuardsAndResolvers 设置为“始终”
{
path: '',
data: {},
runGuardsAndResolvers: 'always'
},
这对我来说就像一个魅力
this.router.navigateByUrl('/', {skipLocationChange: true}).then(()=>
this.router.navigate([<route>]));
小技巧:使用相同的路径和一些虚拟参数。例如-
refresh(){
this.router.navigate(["/same/route/path?refresh=1"]);
}
this.router.navigate(['/pocetna'], { queryParams: { 'refresh': 1 } });
和 route.queryParams.subscribe(val => myRefreshMethod())
,其中 route: ActivatedRoute
被注入到刷新的组件中......希望它有所帮助
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]);
});
}
在参数更改重新加载页面不会发生。这真是一个很好的功能。无需重新加载页面,但我们应该更改组件的值。 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.routeReuseStrategy.shouldReuseRoute = function() {
return false;
// or
return true;
};
找到了一个快速直接的解决方案,不需要修改 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>
希望能帮助到你 :)
从 @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 来使用技巧将刷新组件。
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 不匹配,您将看到标题闪烁“未找到”。
解决方案:
订阅 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 无法为您完成。
id
被读取为字符串,因为整个 URL 都是字符串。使用 new Guid(id)
将字符串转换为 Guid。或者,如果 URL 中不存在 id
,甚至使用 new Guid(id || Guid.empty)
来获得 zeros-Guid。
有点硬核但是
this.router.onSameUrlNavigation = 'reload';
this.router.navigateByUrl(this.router.url).then(() => {
this.router.onSameUrlNavigation = 'ignore';
});
实现 OnInit 并在 route.navigate() 的方法中调用 ngOnInit()
看一个例子:
export class Component implements OnInit {
constructor() { }
refresh() {
this.router.navigate(['same-route-here']);
this.ngOnInit(); }
ngOnInit () {
}
通过为 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})
一种解决方案是传递一个虚拟参数(即以秒为单位的时间),这样链接总是会重新加载:
this.router.navigate(["/url", {myRealData: RealData, dummyData: (new Date).getTime()}])
有不同的方法来刷新当前的路线
更改路由器行为(自 Angular 5.1 起)将路由器 onSameUrlNavigation 设置为“重新加载”。这将在相同的 URL 导航上发出路由器事件。
然后,您可以通过订阅路由来处理它们
您可以将它与 runGuardsAndResolvers 组合使用以重新运行解析器
保持路由器不动
使用 URL 中的当前时间戳传递刷新 queryParam 并订阅路由组件中的 queryParams。
使用 router-outlet 的 activate 事件来获取路由组件。
我在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)
非常令人沮丧的是,Angular still 似乎没有为此提供一个好的解决方案。我在这里提出了一个 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));
}
}
编写一个函数——例如,reloadCurrentPage
。由于 window
是一个可以在 Angular 组件中直接重用的全局对象,因此 window.location.reload()
会重新加载当前活动页面。
function reloadCurrentPage() {
window.location.reload();
}
就我而言:
const navigationExtras: NavigationExtras = {
queryParams: { 'param': val }
};
this.router.navigate([], navigationExtras);
工作正确
假设你要刷新的组件的路由是 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"
后的确切路线。
使用“时间戳”是一种廉价而神奇的方式。
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,
},
});
订阅路由参数更改
// 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'];
});
如果您通过路由器链接更改路由,请按照以下步骤操作:
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
queryParamsMap
主题仅在第一次更新,但在任何后续更新中都没有。
决定何时应该存储路由返回 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;
}
});
'/'
而不是'/DummyComponent'
时,它就像一个魅力