Angular 仅在导航到不同组件时检测路线更改

Angular detect route change only when navigating to a different component

我试图在路由更改时做一些事情(即滚动到顶部)仅当导航到我的应用程序中的不同组件时而不是停留在同一个组件上并且只是通过到同一个组件的路由更改其视图具有不同的查询参数

例如,如果我在 /products?category=kitchen 并导航到 /products?category=bedroom,我不希望执行操作(即滚动到顶部)。

这是我的代码 app.component.ts:

this.router.events.pipe(
  filter(event => event instanceof NavigationEnd)
).subscribe((event: NavigationEnd) => {
  // Would like to check here if user navigates to different component
  if (window) window.scrollTo(0, 0);
});

有人知道我该怎么做吗?

编辑:

由于我不知道你的用例,我只能假设你正在尝试实现以下目标:

在您的应用程序中,可以通过某种方式更改查询参数 "category",例如通过点击一个类别。而不是做

router.navigate(['/products?category=' + newlySelectedCategory]);

并可能对该查询参数作出反应

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

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

  category: string;

  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    // Note: Below 'queryParams' can be replaced with 'params' depending on your requirements
    this.activatedRoute.queryParams.subscribe(params => {
        this.category = params['category'];
    });
  }

}

你可以做到:

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

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

  category: string;

  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    // Note: Below 'queryParams' can be replaced with 'params' depending on your requirements
    this.activatedRoute.queryParams.subscribe(params => {
        this.category = params['category'];
    });
  }

  // This will probably be called from your html code
  selectCategory(category: string) {
     this.category = category;
     this.location.replaceState(`products?category=${category}`);
  }
}

这样就没有路由了


一种可能的方法是不路由,而是将当前的 URL 更改为 this.location.replaceState(假设您在构造函数中注入了 private location: Location)并手动启动相同的进程发生,当你读出 url.

的查询参数时

您可以订阅 ActivatedRoute paramMap 来做您的事情:

this.activatedRoute.paramMap.subscribe(paramMap  =>  {
        this.router.navigate('your child route here');
    });

并确保类别视图是 products 的子路由。

同时在 html 模板 的 产品视图中添加一个路由占位符,子视图将被放置在该位置:

<router-outlet></router-outlet>

您可以阅读有关嵌套的更多信息 routing here:

我想分享我是如何解决这个问题的,以防将来有人遇到类似的事情:

private componentBeforeNavigation = null;
  private setScrollToTopOnNavigation() {
    // Scroll to top only when navigating to a different component
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd)
    ).subscribe((event: NavigationEnd) => {
      let currentRoute = this.route;
      while (currentRoute.firstChild) currentRoute = currentRoute.firstChild;
      if (this.componentBeforeNavigation !== currentRoute.component) {
        if (window) window.scrollTo(0, 0);
      }
      this.componentBeforeNavigation = currentRoute.component;
    });
  }

此代码所做的是为名为 componentBeforeNavigation 的组件使用私有 属性,该组件最初是 null,并且每次触发 Navigation 事件时,subscribe 看看我现在导航的地方和上次导航的地方是不是一样。如果是,这意味着它是到同一组件的导航,我不执行我的特殊操作(在本例中滚动到 window 的顶部),如果不是,这意味着它是到新组件的导航组件。
一件重要的事情是将我导航到的新组件存储在 属性 componentBeforeNavigation 中,以便它始终更新为上次导航