查询参数更改时,路由未更新

Posted

技术标签:

【中文标题】查询参数更改时,路由未更新【英文标题】:On query parameters change, route is not updating 【发布时间】:2018-04-08 18:05:14 【问题描述】:

在我的应用程序中,有多个链接,其中我有一些links 具有相同的route 但具有不同的query parameters

说,我有这样的链接:

.../deposits-withdrawals
.../deposits-withdrawals?id=1
.../deposits-withdrawals?id=2&num=12321344

当我在上述路线之一并且从上面提到的另一条路线本地时,路线不会改变。甚至没有像ngOnInitngOnChanges 这样的任何函数被调用。我已将参数从queryParameters 更改为matrixParameters,但没有成功。我浏览了许多链接和答案。但是,他们都没有解决我的问题。帮我解决这个问题。

谢谢...

编辑:

<button routerLink="/deposits-withdrawals" [queryParams]=" type: 'deposit' ,'productId': selectedBalance.ProductId" class="wallet-btns">DEPOSIT selectedBalance.ProductSymbol</button>
<button routerLink="/deposits-withdrawals" [queryParams]=" type: 'withdrawal' ,'productId': selectedBalance.ProductId " class="wallet-btns">WITHDRAW selectedBalance.ProductSymbol</button>

【问题讨论】:

【参考方案1】:

我曾经遇到过这个问题。你能放一些代码,或者你尝试过的解决方案吗? 我会给你一些对我有用的东西,但你最好给我一些更多的细节,以便我能提供帮助。 假设我们在这里: some_url/deposits-withdrawals 我们希望导航,只更改参数。

    let url = "id=2&num=12321344"
    this.router.navigate(['../', url],  relativeTo: this.route );

希望对你有帮助:/

====================================编辑==== ===============================

您必须检测到查询参数已更改。为此,您可以在组件的构造函数中为 queryParameters 更改添加一个侦听器。这可以使用你的 router 来完成:

    constructor(route:ActivatedRoute)  
        route.queryParams.subscribe(val =>  
            // put the code from ngOnInit here 
        ); 
    

添加此侦听器以检测查询参数更改,意味着您必须将代码从 ngOnInit 函数移动到此侦听器。每次导航时,它都会被调用。

对于导航,您可以使用 html 导航或 ts 导航。如果你希望它在 html 中,你可以使用:

    <button routerLink="/deposits-withdrawals" [queryParams]=" type: 'withdrawal' ,'productId': selectedBalance.ProductId " class="wallet-btns">WITHDRAW selectedBalance.ProductSymbol</button>

【讨论】:

我已经更新了这个问题。请让我知道您还想知道什么。我也会提供的。 好的,你会试试这个吗? ***.com/a/41678403/3428620 ?告诉它是否适合你。它应该工作 从上面的评论中,你的意思是没有办法使用查询参数来做到这一点? constructor(route:ActivatedRoute) route.params.subscribe(val =&gt; // put the code from ngOnInit` 这里 ); ` 表示如果查询参数发生变化,您将向路由添加侦听器。这意味着您必须先导航(使用查询参数,在 html 或 ts 中。例如 然后,你在路由监听器中检测到这些变化。跨度> @AsmaG 谢谢。你是我找到的第一个简单的解决方案。我想知道这么简单的行为如何需要更改提供程序,而我只需要订阅路由。【参考方案2】:

更改参数通常不会导致 ngOnInit。

如果您导航到具有不同参数的同一页面,您可以监听 NavigationEnd 等事件。基于此,您将能够触发您想要的功能。

    import  Router, NavigationEnd  from '@angular/router';
    export class AppComponent 
    ...
      constructor(public userService: UserService, router:Router) 
        router.events.forEach((event) => 
          if(event instanceof NavigationEnd) 
            console.log(location.pathname);
          
          //NavigationStart
          // NavigationEnd
          // NavigationCancel
          // NavigationError
          // RoutesRecognized
        );

【讨论】:

【参考方案3】:

更新查询参数时必须重新调用ngOnInit()。这可以通过以下方式实现:

import  Router  from '@angular/router';
constructor(private router: Router) 
   this.router.routeReuseStrategy.shouldReuseRoute = () => false;

【讨论】:

【参考方案4】:

我这样解决了这个问题。

假设您有一个容器news-list.component.tsngOnInit。它将当前的 queryParams 保存在 currentFilters 中,如果没有它们,则发出简单的 GET 请求,否则发出 POST 请求。

    ngOnInit() 
      this.route.queryParams.subscribe(queryParams => 
        if (!!queryParams) 
          this.currentFilters = <NewsFilter>...queryParams, offset: 0, size: 6;
          this.news$ = this.newsPostsService.getNewsByFilter(this.currentFilters);
         else 
          this.news$ = this.newsPostsService.getMainNews();
        
      );
    

然后创建一个组件&lt;news-rubric&gt;&lt;/news-rubric&gt;,它具有以下视图。你经过currentFilters 并取走rubricClick,然后处理它。

news-list.component.html

    <ml-news-rubrics [currentFilters]="currentFilters"
                     (rubricClicked)="onRubricFilter($event)"
    ></ml-news-rubrics>

news-list.component.ts

    onRubricFilter(filters: NewsFilter) 
      this.currentFilters = ...filters;
      this.router.navigate([], queryParams: filters, relativeTo: this.route);
    

然后在news-rubric.component.ts 中执行如下操作:

    onRubricClicked(rubricId: string) 
      // check if filter exists and if not then put ID in filter
      if (!this.currentFilters.filterByAnyRubricIds)  
        this.putIdInFilter('filterByAnyRubricIds', rubricId, this.currentFilters.filterByAnyRubricIds);
       else 
        // check if clicked ID is not in filter. put in filter
        if (!this.currentFilters.filterByAnyRubricIds.includes(rubricId))  
          this.putIdInFilter('filterByAnyRubricIds', rubricId, this.currentFilters.filterByAnyRubricIds);
         else  
          // if ID in filter remove it from filter
          this.removeIdFromFilter('filterByAnyRubricIds', rubricId, this.currentFilters.filterByAnyRubricIds);
        
      
      this.rubricClicked.emit(this.currentFilters);
    

有最棘手的代码。它通过使用过滤后的 ID 更新其 key 来创建新过滤器。

    private putIdInFilter(key: string, value: any, list: any) 
      if (!list || !(list instanceof Array)) 
        if (!list) 
          this.currentFilters = ...this.currentFilters, [key]: [value];
         else 
          this.currentFilters = ...this.currentFilters, [key]: [this.currentFilters[key], value];
        
       else 
        this.currentFilters = ...this.currentFilters, [key]: [...this.currentFilters[key], value];
      
    

    private removeIdFromFilter(key: string, value: any, list: any) 
      if (!list || !(list instanceof Array)) 
        this.currentFilters = <NewsFilter>
          ...this.currentFilters, [key]: null
        ;
        return;
      
      const filteredValues = [...list.filter(i => i !== value)];
      if (filteredValues.length > 0) 
        this.currentFilters = <NewsFilter>
          ...this.currentFilters, [key]: filteredValues
        ;
       else 
        delete this.currentFilters[key];
      
    

NewsFilter 只是类似于QueryParams 的接口,带有需要过滤的键。

【讨论】:

以上是关于查询参数更改时,路由未更新的主要内容,如果未能解决你的问题,请参考以下文章

路由更改时使用新的路由参数更新 redux 状态

Vue路由器更改查询参数时防止滚动到顶部

查询参数更改时,角度路由器导航不会加载页面

React 路由器更改 url 但未更新上下文

如何获取路由器未加载的组件中路由更改的当前路由参数

更改Query Param不刷新路由