Bộ định tuyến điều hướng không gọi ngOnInit khi cùng một trang


86

Tôi đang gọi router.navigatetrên cùng một trang với một số tham số chuỗi truy vấn. Trong trường hợp này, ngOnInit()không gọi. Đó là theo mặc định hay tôi cần thêm bất cứ điều gì khác?

Câu trả lời:


136

Bạn có thể tiêm ActivatedRoutevà đăng kýparams

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

Bộ định tuyến chỉ phá hủy và tạo lại thành phần khi nó điều hướng đến một tuyến đường khác. Khi chỉ các tham số định tuyến hoặc tham số truy vấn được cập nhật nhưng tuyến đường vẫn như cũ, thành phần sẽ không bị hủy và tạo lại.

Một cách khác để buộc tạo lại thành phần là sử dụng chiến lược tái sử dụng tùy chỉnh. Xem thêm Bộ định tuyến Angular2 2.0.0 không tải lại các thành phần khi cùng một url được tải với các thông số khác nhau? (dường như vẫn chưa có nhiều thông tin về cách triển khai)


1
đăng ký này không hoạt động nó sẽ chỉ kích hoạt trên init
Osanda Wedamulla

@OsandaWedamulla sau đó dành riêng cho mã của bạn. Tuy nhiên, thật khó để nói nếu không có thêm chi tiết
Günter Zöchbauer

1
Bạn cũng không cần phải hủy đăng ký hay việc này được thực hiện tự động?
rain01

1
@ rain01 theo quy tắc chung, bạn nên hủy đăng ký rõ ràng trong cpde của mình khi bạn đã đăng ký rõ ràng. Nếu bạn có mã trên trong thành phần gốc của mình thì việc hủy đăng ký là không cần thiết vì thời gian tồn tại của thành phần gốc thường giống với thời gian tồn tại của toàn bộ ứng dụng Angular.
Günter Zöchbauer

103

Bạn có thể điều chỉnh tốc độ sử dụng lại trên Router.

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

2
Thao tác này sẽ khởi tạo ngInit của mọi thành phần trên trang.
jforjs

2
Chà, @Pascal, bạn đã buộc tôi phải đăng nhập vào SO chỉ để bỏ phiếu cho câu trả lời của bạn. Tôi muốn nói thêm rằng trong góc 6 bạn cũng phải thêm onSameUrlNavigation: 'reload'vào các đối tượng cấu hình như sau: RouterModule.forRoot(appRoutes, {onSameUrlNavigation: 'reload'}). Tuy nhiên, Coud không nói cho bất kỳ phiên bản Angular nào khác.
Hildy

1
@ Xin chào, tôi buộc phải làm như vậy :) Cảm ơn @Pascal! nếu bạn thích lambda, bạn có thể làm điều này this.router.routeReuseStrategy.shouldReuseRoute = () => false;
nick

1
@Swaprks tôi đã tạo ra một routing.module.ts và đặt mã như constructor này
Pascal

1
@Swaprks .. Tôi gặp sự cố tương tự và muốn thử câu trả lời của bạn ở trên. Nhưng nó không cho tôi biết nhiều điều khi là một người mới bắt đầu trong lĩnh vực này. Chính xác thì tôi phải đặt đoạn mã này ở đâu trong mã? Tôi có phải thay đổi bất cứ điều gì trong đoạn mã không (ví dụ: ´ Chức năng () ´)? Nếu bạn đã tạo một tệp mới với tên routing.module.ts, thì nó sẽ tương tác với các tệp khác như thế nào? Ngoài ra còn có một tệp tên là app-routing.module.ts được tạo tự động.
edn

21

Góc 9

Tôi đã sử dụng những điều sau đây và nó hoạt động.

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

1
Ngoài ra, cũng sử dụng lambda thay vì ở trên, this.router.routeReuseStrategy.shouldReuseRoute = () => false;
Dhwanil Patel

Hoạt động trong Angular 8.
Kishan Vaishnav

2
Điều này sẽ thay đổi hành vi của bộ định tuyến trên ứng dụng hay chỉ kích hoạt một lần cho điều này cụ thể navigate()?
Nghỉ nửa buổi

8

Bạn có thể cần tải lại trang không? Đây là giải pháp của tôi: Tôi đã thay đổi @NgModule (trong tệp app-routing.module.ts trong trường hợp của tôi):

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

'Các tuyến đường' ở đây là gì.
Dhwanil Patel

@DhwanilPatel các tuyến ứng dụng Angular của bạn. Ví dụ: "const route: Routes = [{path: 'precision-center', component: CrisisListComponent}, {path: 'Heroes', component: HeroListComponent},]" angle.io/guide/router#register-router-and -routes
Dionis Oros

1

NgOnInitsẽ được gọi một lần khi một thể hiện được tạo. Đối với cùng một trường hợp NgOnInitsẽ không được gọi lại. Để gọi nó, cần phải hủy thể hiện đã tạo.


1

Trên phương pháp điều hướng của bạn,

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

1

Tôi đã gặp vấn đề tương tự, ngoài ra, tôi nhận được cảnh báo:

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

Trang web này cung cấp giải pháp tốt nhất:

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

Về vấn đề này, tôi muốn biết cách xử lý vấn đề khi bạn chỉ cần làm mới trang bằng tuyến mới. Trong trường hợp đó, cảnh báo NgZone vẫn sẽ xuất hiện.
Siddhant

0

Vấn đề này có thể xuất phát từ thực tế là bạn không chấm dứt đăng ký của mình bằng ngOnDestroy. Đây là cách để hoàn thành.

  1. Nhập đăng ký rxjs sau. import { Subscription } from 'rxjs/Subscription';

  2. Thêm OnDestory vào Angular Core Import của bạn. import { Component, OnDestroy, OnInit } from '@angular/core';

  3. Thêm OnDestory vào lớp xuất của bạn. export class DisplayComponent implements OnInit, OnDestroy {

  4. Tạo thuộc tính đối tượng với giá trị Đăng ký từ rxjs trong lớp xuất của bạn cho mỗi đăng ký trên thành phần. myVariable: Subscription;

  5. Đặt giá trị đăng ký của bạn thành MyVariable: Đăng ký. this.myVariable = this.rmanagerService.getRPDoc(books[i].books.id).subscribe(value => {});

  6. Sau đó, ngay bên dưới ngOninit đặt móc vòng đời ngOnDestory () và đưa vào tuyên bố hủy đăng ký cho đăng ký của bạn. Nếu bạn có nhiều, hãy thêm nhiều ngOnDestroy() { this.myVariable.unsubscribe(); }


Tôi tiếp tục nhập ngOnDestorythay vì ngOnDestroychính mình ;-)
Simon_Weaver

0

Tạo một đường dẫn khác cho cùng một thành phần trong mảng các tuyến đường.

const route: Routes = [{path: "app", component: MyComponent}, {path: "app-reload", component: MyComponent}];

Nếu URL hiện tại là "ứng dụng" thì hãy điều hướng bằng cách sử dụng "tải lại ứng dụng" và ngược lại.


0

Đây là bộ sưu tập các ý tưởng hay nhất trên trang này với nhiều thông tin hơn

Giải pháp 1 - Sử dụng đăng ký tham số:

Hướng dẫn: https://angular-2-training-book.rangle.io/routing/routeparams#reading-route-parameters

Tài liệu: https://angular.io/api/router/ActiisedRoute#params

Trong mỗi thành phần định tuyến của bạn sử dụng các biến tham số bao gồm những điều sau:

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

Một số vấn đề phổ biến với mã này là đăng ký không đồng bộ và có thể khó xử lý hơn. Ngoài ra, bạn không thể quên hủy đăng ký trên ngOnDestroy nếu không điều tồi tệ có thể xảy ra.

Điều tốt là đây là cách được ghi chép và phổ biến nhất để xử lý vấn đề này. Cũng có một cải tiến về hiệu suất làm theo cách này vì bạn đang sử dụng lại mẫu thay vì hủy và tạo lại mỗi khi bạn truy cập một trang.

Giải pháp 2 - shouldReuseRoute / onSameUrlNavigation:

Tài liệu: https://angular.io/api/router/ExtraOptions#onSameUrlNavigation

Tài liệu: https://angular.io/api/router/RouteReuseStrategy#shouldReuseRoute

Tài liệu: https://angular.io/api/router/ActiisedRouteSnapshot#params

Tìm RouterModule.forRootvị trí đặt trong dự án của bạn (thường được tìm thấy trong app-routing.module.ts hoặc app.module.ts):

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

// ...

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

Sau đó, trong AppComponent thêm những thứ sau:

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

        // ...
    }

    // ...
}

Cuối cùng, trong các thành phần định tuyến của bạn, bây giờ bạn có thể xử lý các biến tham số như sau:

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;

        // ...
    }

    // ...
}

Các vấn đề phổ biến với giải pháp này là nó không phổ biến. Ngoài ra, bạn đang thay đổi hành vi mặc định của khung công tác Angular, vì vậy bạn có thể gặp phải các vấn đề mà mọi người thường không gặp phải.

Điều tốt là tất cả mã của bạn đều đồng bộ và dễ hiểu hơn.


-1

Cân nhắc việc chuyển mã bạn có trong ngOnInit vào ngAfterViewInit. Cái sau dường như được gọi trên điều hướng bộ định tuyến và sẽ giúp bạn trong trường hợp này.


3
rằng doesnt thực sự xảy ra
Nadav

-7

Khi bạn muốn bộ định tuyến điều hướng trên cùng một trang và muốn gọi ngOnInit (), vì vậy bạn làm như vậy, ví dụ:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.