119

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

4

14 回答 14

172

您可以注入ActivatedRoute并订阅params

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

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

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

于 2017-01-16T14:14:57.717 回答
126

您可以调整路由器上的重用策略。

constructor(private router: Router) {
    // override the route reuse strategy
    this.router.routeReuseStrategy.shouldReuseRoute = function() {
        return false;
    };
}
于 2017-12-15T07:29:11.293 回答
38

角 9

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

onButtonClick() {
    this.router.routeReuseStrategy.shouldReuseRoute = function () {
        return false;
    }
    this.router.onSameUrlNavigation = 'reload';
    this.router.navigate('/myroute', { queryParams: { index: 1 } });
}
于 2020-05-05T20:20:59.217 回答
9

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

@NgModule({
  imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})] })
于 2018-09-26T07:35:27.557 回答
4

这是此页面上最好的想法的集合,其中包含更多信息

解决方案 1 - 使用参数订阅:

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

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

于 2020-04-10T06:27:08.780 回答
4

在您的导航方法上,

this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.router.onSameUrlNavigation = 'reload';
this.router.navigate(['/document'], {queryParams: {"search": currentSearch}});
于 2020-05-26T07:12:15.653 回答
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]));
  }
于 2020-07-09T09:50:07.973 回答
1

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

于 2017-01-16T14:19:43.047 回答
0

这个问题很可能是因为您没有使用 ngOnDestroy 终止订阅。这是完成的方法。

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

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

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

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

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

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

于 2018-05-13T17:44:50.857 回答
0

ngOnInit这是Router Navigate在同一页面时不调用该函数的最佳解决方案

// override the route reuse strategy
this.router.routeReuseStrategy.shouldReuseRoute = function() {
    return false;
};
于 2022-01-25T12:16:45.857 回答
0

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

常量路由:路由 = [ { 路径:“app”,组件:MyComponent },{ 路径:“app-reload”,组件:MyComponent }];

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

于 2019-11-28T15:11:06.820 回答
0
// this code is for redirecting to the dashboard page with calling ngOnInIt
    this.router.routeReuseStrategy.shouldReuseRoute = () => false;
    this.router.onSameUrlNavigation = 'reload';
    this.router.navigate(['./dashboard']);

这应该有效,并且应该只用于特殊情况。当您在重定向后不必进行太多导航时,您可以使用此。否则有时会搞砸。请注意,您始终可以在需要时将“routeReuseStrategy”设置为 true。

于 2022-01-29T07:03:32.950 回答
-1

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

于 2017-03-15T21:05:23.977 回答
-8

当您想在同一页面上进行路由器导航并想调用 ngOnInit() 时,您确实喜欢这样,例如,

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

于 2019-04-04T10:46:22.093 回答