Angular 11 数据未更改时未更新可观察到的路由器数据

Angular 11 Router data observable not updated when data has not changed

我有这个 Angular 解析器:

@Injectable()
export class DataResolver implements Resolve<any> {

    constructor(private apiService: ApiService) {}
    
    public resolve(route: ActivatedRouteSnapshot): any {
      const data = {
        param1: route.queryParamMap.get('param1'),
        param2: route.queryParamMap.get('param2'),
      };
      return this.apiService.search(data);
    }
}

apiService.search 方法如下所示:

public search(data): Observable<any> {
  let params = new HttpParams(); 
  for (const key in data) {
    if (data.hasOwnProperty(key)) {
      const value = data[key];
      if (value) {
        params = params.set(key, value);
      }
    }
  }

  return this.http.get<any>(`${API_URL}/endpoint`, { params });
}

然后我有一个组件可以订阅 ActivatedRoute 数据的变化:

route.data.subscribe((data) => {
  console.log(data);
});

路线如下:

{
  component: HomeComponent,
  path: '/',
  resolve: {
    data: DataResolver,
  },
  runGuardsAndResolvers: 'paramsOrQueryParamsChange',
}

问题是,订阅处理程序只有在 data 实际发生变化时才会被调用,而不管解析器的 resolve 方法是否已被调用。特别是,如果两个(或更多)后续的 resolve 调用解析一个空数组,那么行 console.log(data) 只会在第一次被调用。

这是预期的行为吗?我可以强制 observable 发出新值吗?

我的目标是每次 resolve 解析一个空数组时都显示一条消息,无论它之前是否为空。

您不必要地将可观察对象包装在承诺中并解决了它。尝试像这样重写解析器。

@Injectable()
export class DataResolver implements Resolve<any> {
    constructor(private apiService: ApiService) {}

    public resolve(route: ActivatedRouteSnapshot): any {
        const data = {
            param1: route.queryParamMap.get("param1"),
            param2: route.queryParamMap.get("param2"),
        };

        return this.apiService.search(data);
    }
}

我还会考虑使用 HttpPrams

清理您的 API 服务
// import { HttpClient,HttpParams } from '@angular/common/http';
public search(data): Observable<any> {
  let params = new HttpParams({ fromObject: data });
  return this.http.get<any>(`${API_URL}/endpoint`, { params });
}

您可能需要将解析器添加到您的路由 table

RouterModule.forRoot([{
  path: 'yourRoute',
  component: YourComponent,
  resolve: {
    yourDataWillBeInThisProperty: DataResolver
  }
}])

如果您想要重新加载组件,您可能需要更改路由器模块中的 onSameUrlNavigation 属性

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

我不建议使用 onSameUrlNavigation 来解决你的问题,但我会订阅 route.queryParams observable 并在那里触发搜索。

在你的组件中

ngOnInit(){
  this.sub = this.route.queryParams.subscribe(() => { this.data = this.route.snapshot.data.data; }); 
  // don't forget to unSubscribe
}