Router Navigate在同一页面时不会调用ngOnInit

时间:2017-01-16 14:12:28

标签: angular navigateurl ngoninit

我在同一页面上使用一些查询字符串参数调用router.navigate。在这种情况下,ngOnInit()不会调用。是默认情况下还是我需要添加其他内容?

12 个答案:

答案 0 :(得分:66)

您可以注入ActivatedRoute并订阅params

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

路由器仅在导航到其他路径时销毁并重新创建组件。当只更新路由参数或查询参数但路由相同时,组件不会被销毁并重新创建。

强制重新创建组件的另一种方法是使用自定义重用策略。另请参阅Angular2 router 2.0.0 not reloading components when same url loaded with different parameters?(似乎没有太多可用的信息,但是如何实现它)

答案 1 :(得分:52)

您可以在路由器上调整reuseStrategy。

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

答案 2 :(得分:24)

角度9

我已经使用了以下内容并且有效。

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

答案 3 :(得分:3)

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

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

答案 4 :(得分:1)

创建实例时,将会调用 NgOnInit 一次。对于相同的实例, NgOnInit 不会再次被调用。为了调用它,有必要销毁创建的实例。

答案 5 :(得分:1)

这个问题可能来自于您没有使用ngOnDestroy终止订阅这一事实。以下是如何完成的工作。

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

  2. 将OnDestory添加到Angular Core Import。 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(); }

答案 6 :(得分:1)

在您的导航方法上,

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

答案 7 :(得分:1)

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

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

This网站提供了最佳解决方案:

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

答案 8 :(得分:0)

考虑将ngOnInit中的代码移动到ngAfterViewInit中。 后者似乎在路由器导航上被调用,在这种情况下应该会帮助你。

答案 9 :(得分:0)

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

const路线:路线= [{ 路径:“应用”, 组件:MyComponent }, { 路径:“ app-reload”, 组件:MyComponent }];

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

答案 10 :(得分: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框架的默认行为,因此您可能会遇到人们通常不会遇到的问题。

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

答案 11 :(得分:-2)

当您想在同一页面上路由浏览器并想调用ngOnInit()时,您确实喜欢这样,

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