路由器导航在同一页面时不调用ngOnInit


Answers:


136

您可以注入ActivatedRoute并订阅params

constructor(route:ActivatedRoute) {
  route.params.subscribe(val => {
    // put the code from `ngOnInit` here
  });
}

路由器仅在导航到其他路由时销毁并重新创建组件。如果仅更新路由参数或查询参数,但路由相同,则不会破坏和重新创建组件。

强制重新创建组件的另一种方法是使用自定义重用策略。另请参阅Angular2路由器2.0.0在使用不同参数加载相同的url时是否不重新加载组件?(似乎没有太多可用信息,如何实现)


1
此订阅无法正常运行,只会在初始化时触发
Osanda Wedamulla,

然后,@ OsandaWedamulla专门针对您的代码。很难说没有,虽然更多的细节
君特Zöchbauer

1
您是否也不需要取消订阅,或者这是自动完成的?
rain01

1
根据经验,@ rain01应该明确地在cpde中取消订阅。如果您的根组件中包含上述代码,则取消订阅是多余的,因为根组件的生存期通常与整个Angular应用程序的生存期相同。
君特Zöchbauer

102

您可以在路由器上调整复用策略。

constructor(private router: Router) {
    // override the route reuse strategy
    this.router.routeReuseStrategy.shouldReuseRoute = function() {
        return false;
    };
}

2
这将启动页面上每个组件的ngInit。
jforjs

2
好吧,@ Pascal,您强迫我登录SO只是为了投票给您答案。我想补充一点,在角6还必须添加onSameUrlNavigation: 'reload'到配置的对象,像这样:RouterModule.forRoot(appRoutes, {onSameUrlNavigation: 'reload'})。但是,Coudn不代表任何其他Angular版本。
希尔迪,

1
@Hildy,我被迫做同样的事情:)谢谢@Pascal!如果您喜欢lambda,则可以执行以下this.router.routeReuseStrategy.shouldReuseRoute =()=> false;
尼克,

1
@Swaprks我创建了routing.module.ts并将代码放置为此构造函数
Pascal

1
@Swaprks ..我有一个类似的问题,想尝试一下上面的答案。但这并不能告诉我这个领域的初学者。我应该在代码中的哪个位置放置此代码段?我是否应该更改代码段中的任何内容(例如“ function()”)?如果您创建了一个名为routing.module.ts的新文件,那么它应该如何与其他文件交互?还有一个名为app-routing.module.ts的文件会自动创建。
edn

21

角度9

我已经使用了以下方法,并且有效。

onButtonClick() {
    this.router.routeReuseStrategy.shouldReuseRoute = function () {
        return false;
    }
    this.router.onSameUrlNavigation = 'reload';
    this.router.navigate('/myroute', { queryParams: { index: 1 } });
}

1
另外,也可以使用lambda代替上面的代码,this.router.routeReuseStrategy.shouldReuseRoute =()=> false;
Dhwanil Patel

工程在角8
基尚Vaishnav

2
这会改变路由器在整个应用程序中的行为,还是仅针对此特定事件触发一次navigate()
Halfist

8

您可能需要重新加载页面吗?这是我的解决方案:我已经更改了@NgModule(在我的情况下为app-routing.module.ts文件):

@NgModule({
  imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})] })

这里的“路线”是什么。
Dhwanil Patel

@DhwanilPatel您的Angular应用路线。例如“ const route:Routes = [{路径:“危机中心”,组件:CrissListComponent},{路径:“英雄”,组件:HeroListComponent},]” angular.io/guide/router#register-router-and路线
Dionis Oros

1

NgOnInit创建实例时将调用一次。对于同一实例,NgOnInit将不会再次调用。为了进行调用,必须销毁创建的实例。


1

在您的导航方法上,

this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.router.onSameUrlNavigation = 'reload';
this.router.navigate(['/document'], {queryParams: {"search": currentSearch}});

1

我遇到了同样的问题,另外我得到了警告:

did you forget to call `ngZone.run()`

站点提供了最佳的解决方案:

import { Router } from '@angular/router';
import { NgZone } from '@angular/core';

...

  constructor(
    private ngZone:NgZone,
    private _router: Router
  ){ }

  redirect(to) {
    // call with ngZone, so that ngOnOnit of component is called
    this.ngZone.run(()=>this._router.navigate([to]));
  }

对此,我希望知道当您使用新路线简单地刷新页面时如何处理该问题。在这种情况下,NgZone警告将仍然存在。
悉达特

0

此问题可能是由于您没有使用ngOnDestroy终止订阅而引起的。这是完成任务的方法。

  1. 引入以下rxjs订阅导入。 import { Subscription } from 'rxjs/Subscription';

  2. 将OnDestory添加到Angular Core导入中。 import { Component, OnDestroy, OnInit } from '@angular/core';

  3. 将OnDestory添加到您的导出类。 export class DisplayComponent implements OnInit, OnDestroy {

  4. 在组件的每个订阅的导出类下,创建一个对象属性,其值为rxjs中的Subscription。 myVariable: Subscription;

  5. 将您的订阅的值设置为MyVariable:订阅。 this.myVariable = this.rmanagerService.getRPDoc(books[i].books.id).subscribe(value => {});

  6. 然后,在ngOninit的正下方放置ngOnDestory()生命周期挂钩,并在您的取消订阅语句中进行订阅。如果有多个,请添加更多 ngOnDestroy() { this.myVariable.unsubscribe(); }


我也一直在打字ngOnDestory而不是ngOnDestroy自己;-)
Simon_Weaver

0

为路由数组中的同一组件创建一个不同的路径。

const route:Routes = [{路径:“ app”,组件:MyComponent},{路径:“ app-reload”,组件:MyComponent}];

如果当前URL是“ app”,则使用“ app-reload”进行导航,反之亦然。


0

这是此页面上最佳创意的集合,其中包含更多信息

解决方案1-使用params订阅:

教程:https//angular-2-training-book.rangle.io/routing/routeparams#reading-route-parameters

文件:https//angular.io/api/router/ActivatedRoute#params

在每个使用参数变量的路由组件中,包括以下内容:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';

// ...

@Component({
    // ...
})
export class MyComponent implements OnInit, OnDestroy {
    paramsSub: Subscription;

    // ...

    constructor(activeRoute: ActivatedRoute) {

    }

    public ngOnInit(): void {
        // ...
        this.paramsSub = this.activeRoute.params.subscribe(val => {
            // Handle param values here
        });

        // ...
    }

    // ...

    public ngOnDestroy(): void {
        // Prevent memory leaks
        this.paramsSub.unsubscribe();
    }
}

此代码的一些常见问题是订阅是异步的,并且处理起来比较棘手。同样,您也不能忘记取消订阅ngOnDestroy,否则可能会发生坏事。

好消息是,这是处理此问题的最有据可查和最常用的方法。这样还可以提高性能,因为您正在重用模板,而不是每次访问页面时都要销毁并重新创建。

解决方案2-shouldReuseRoute / onSameUrlNavigation:

文件:https//angular.io/api/router/ExtraOptions#onSameUrlNavigation

文件:https//angular.io/api/router/RouteReuseStrategy#shouldReuseRoute

文件:https//angular.io/api/router/ActivatedRouteSnapshot#params

查找RouterModule.forRoot项目中的位置(通常在app-routing.module.ts或app.module.ts中找到):

const routes: Routes = [
   // ...
];

// ...

@NgModule({
    imports: [RouterModule.forRoot(routes, {
        onSameUrlNavigation: 'reload'
    })],
    exports: [RouterModule]
})

然后在AppComponent中添加以下内容:

import { Component, OnInit} from '@angular/core';
import { Router } from '@angular/router';

// ...
@Component({
    // ...
})
export class AppComponent implements OnInit {
    constructor(private router: Router) {
    }

    ngOnInit() {
        // Allows for ngOnInit to be called on routing to the same routing Component since we will never reuse a route
        this.router.routeReuseStrategy.shouldReuseRoute = function() {
            return false;
        };

        // ...
    }

    // ...
}

最后,您现在可以在路由组件中处理如下参数变量:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

// ...

@Component({
    // ...
})
export class MyComponent implements OnInit {
    // ...

    constructor(activeRoute: ActivatedRoute) {

    }

    public ngOnInit(): void {
        // Handle params
        const params = +this.activeRoute.snapshot.params;

        // ...
    }

    // ...
}

此解决方案的常见问题是它并不常见。另外,您正在更改Angular框架的默认行为,因此您可能会遇到人们通常不会遇到的问题。

好消息是所有代码都是同步的,更易于理解。



-7

当您想在同一页面上导航时,并想调用ngOnInit()时,您可以这样做,例如,

this.router.navigate(['category / list',category]).then(()=> window.location.reload());

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.