Я телефоную router.navigate
на ту саму сторінку з деякими параметрами рядка запиту. У цьому випадку ngOnInit()
не дзвонить. Це за замовчуванням чи мені потрібно додати ще щось?
Я телефоную router.navigate
на ту саму сторінку з деякими параметрами рядка запиту. У цьому випадку ngOnInit()
не дзвонить. Це за замовчуванням чи мені потрібно додати ще щось?
Відповіді:
Ви можете зробити ін'єкцію ActivatedRoute
та підписатися на неїparams
constructor(route:ActivatedRoute) {
route.params.subscribe(val => {
// put the code from `ngOnInit` here
});
}
Маршрутизатор руйнує та відтворює компонент лише тоді, коли він переходить на інший маршрут. Коли оновлюються лише параметри маршруту або параметри запиту, але маршрут однаковий, компонент не буде знищений і відтворений.
Альтернативний спосіб примусити компонент до відтворення - використовувати власну стратегію повторного використання. Див. Також маршрутизатор Angular2 2.0.0, який не перезавантажує компоненти, коли однакова URL-адреса завантажена з різними параметрами? (схоже, поки що немає багато інформації, як її реалізувати)
Ви можете налаштувати стратегію повторного використання на маршрутизаторі.
constructor(private router: Router) {
// override the route reuse strategy
this.router.routeReuseStrategy.shouldReuseRoute = function() {
return false;
};
}
onSameUrlNavigation: 'reload'
до об'єкту конфігурації наступним чином: RouterModule.forRoot(appRoutes, {onSameUrlNavigation: 'reload'})
. Однак не може говорити про інші версії Angular.
Я використав наступне, і це спрацювало.
onButtonClick() {
this.router.routeReuseStrategy.shouldReuseRoute = function () {
return false;
}
this.router.onSameUrlNavigation = 'reload';
this.router.navigate('/myroute', { queryParams: { index: 1 } });
}
navigate()
?
Вам, мабуть, потрібно перезавантажити сторінку? Це моє рішення: я змінив @NgModule ( у моєму випадку у файлі app-routing.module.ts ):
@NgModule({
imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})] })
NgOnInit
буде викликано один раз при створенні екземпляра. Бо той самий екземпляр NgOnInit
більше не буде викликаний. Для його виклику необхідно знищити створений екземпляр.
На вашому методі навігації,
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.router.onSameUrlNavigation = 'reload';
this.router.navigate(['/document'], {queryParams: {"search": currentSearch}});
У мене була та ж проблема, крім того, я отримав попередження:
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]));
}
Ця проблема, швидше за все, пов’язана з тим, що ви не припиняєте свої підписки за допомогою ngOnDestroy. Ось як це зробити.
Введіть наступний імпорт передплати на rxjs.
import { Subscription } from 'rxjs/Subscription';
Додайте OnDestory до свого Імпорту кутового ядра.
import { Component, OnDestroy, OnInit } from '@angular/core';
Додайте OnDestory до свого класу експорту.
export class DisplayComponent implements OnInit, OnDestroy {
Створіть властивість об’єкта зі значенням Subscription з rxjs під вашим класом експорту для кожної підписки на компонент.
myVariable: Subscription;
Встановіть для вашої передплати значення MyVariable: Підписки.
this.myVariable = this.rmanagerService.getRPDoc(books[i].books.id).subscribe(value => {});
Потім прямо під ngOninit помістіть гачок життєвого циклу ngOnDestory () і поставте свою заяву про відмову від підписки на свою підписку. Якщо у вас кілька, додайте більше
ngOnDestroy() {
this.myVariable.unsubscribe();
}
ngOnDestory
замість ngOnDestroy
себе ;-)
Ось збірка найкращих ідей на цій сторінці з додатковою інформацією
Рішення 1 - Використовуйте підписку на params:
Підручник: https://angular-2-training-book.rangle.io/routing/routeparams#reading-route-parameters
Документи: https://angular.io/api/router/ActivatedRoute#params
У кожному з ваших компонентів маршрутизації, які використовують змінні param, є таке:
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, щоб ви могли зіткнутися з проблемами, з якими люди зазвичай не стикаються.
Добре, що весь ваш код синхронний і легший для розуміння.
Подумайте про переміщення коду, який ви мали в ngOnInit, у ngAfterViewInit. Останнє, здається, називається навігацією маршрутизатора і має допомогти вам у цьому випадку.
Коли ви хочете, щоб маршрутизатор переміщався по тій самій сторінці і хочете викликати ngOnInit (), то вам це подобається, наприклад,
this.router.navigate (['категорія / список', категорія]). then (() => window.location.reload ());