【问题标题】:Routing with option params with ? and &带有选项参数的路由?和 &
【发布时间】:2019-03-21 18:25:01
【问题描述】:

我正在尝试深入了解 Angular 的路线,但没有成功。我正在尝试做的是使用角度的路线捕获 url 中的每个参数。

让我们以这个网址为例:

http://localhost:4200/PUC/#/P3?MODE=P&USER=AE13356&PROJECT=00001&PROTOCOL=00002&VERSION=1

我正在尝试将参数分配给一些变量。

所以我所做的(错误)是这样的:

路线:

 RouterModule.forRoot(
      [
        { path: "", component: AppComponent, pathMatch: 'full'},
      ],
    )

组件:

@Component({
  selector: 'app-main',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{

  constructor(
    private router: Router,
    private route: ActivatedRoute
  ) { }

  ngOnInit(){
    let queryParams = this.route.snapshot.queryParams;
    const mode = queryParams['MODE'];

    console.log("ID > " + mode);
  }
}

queryParams 始终是一个空对象。我错过了什么?

编辑

使用location.href 我已经得到了整个url,我可以用这种方式对我得到的数据做一些逻辑吗?基本上我要做的是如果PROJECT 有一个值,则加载一个组件,如果PROJECT 不在url 中,则加载另一个组件。

【问题讨论】:

    标签: angular routes angular-routing angular-components


    【解决方案1】:

    Snapshot 不会在查询参数发生变化时为您提供更新的查询参数。但是在 ActivatedRoute 上有一个 queryParams BehaviorSubject 可以为您提供更新的查询参数。

    您应该为此使用route.queryParams.subscribe

    现在,我不确定如何处理您网址中的 #。但没有它,因为你有 PUC 作为一个路由和 P3 作为它的孩子,你的 Route Config 看起来像这样:

    RouterModule.forRoot([
      {
        path: 'PUC/:segment',
        component: PucComponent
      }
    ])
    

    至于路由PIC,我们正在加载PucComponent,你应该在那里阅读queryParams

    import { Component, OnInit } from '@angular/core';
    import { Router, ActivatedRoute } from '@angular/router';
    
    @Component({
      selector: 'app-puc',
      templateUrl: './puc.component.html',
      styleUrls: ['./puc.component.css']
    })
    export class PucComponent implements OnInit {
    
      constructor(
        private router: Router,
        private route: ActivatedRoute
      ) { }
    
      ngOnInit(){
        this.route.queryParams
          .subscribe(queryParams => console.log(queryParams));
      }
    
    }
    

    这里有一个Sample StackBlitz 供您参考。

    【讨论】:

    • 遗憾的是 mode 仍然未定义
    • (编辑了我的问题)
    • @JacopoSciampi,我不太确定您网址中的 #。但如果那不存在,我已经更新了我的答案。我在某处读到,通常较旧的浏览器会在您的网址中添加#
    【解决方案2】:

    您所要做的就是将查询参数的值包含在 " " 中。

    <a [routerLink]="['/PUC','P3']" [queryParams]="{key:'stringvalue'}">Click here</a>
    

    如果查询参数的值为数字,则不需要括在" "中。

    <a [routerLink]="['/PUC','P3']" [queryParams]="{key:number}">Click here</a>
    

    app.moudle.ts

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { FormsModule } from '@angular/forms';
    import { RouterModule,Routes } from '@angular/router';
    import { HelloComponent } from './hello.component';
    import { AppComponent } from './app.component';
    
    const routes:Routes = [{
           path:'PUC/P3', component:HelloComponent
        }]
    @NgModule({
      imports:[ BrowserModule,FormsModule ,RouterModule.forRoot(routes,{useHash:true})],
      declarations: [ AppComponent, HelloComponent ],
      bootstrap:    [ AppComponent ]
    })
    export class AppModule { }
    

    app.component.html

    <a [routerLink]="['/PUC','P3']" [queryParams]="{ MODE: 'p', USER:'AE13356',PROJECT:00001,PROTOCOL:00002,VERSION:1}"> Click here</a>
    <router-outlet></router-outlet>
    

    hello.component.ts

    import { Component, OnInit } from '@angular/core';
    import { ActivatedRoute } from '@angular/router';
    
    @Component({
      selector: 'app-hello',
      template: `<h2>Check Console for Output</h2>`,
    })
    export class HelloComponent implements OnInit {
      constructor(private route:ActivatedRoute){}
      ngOnInit(){
        this.route.queryParams.subscribe((query)=>{
          console.log(query);
          console.log("MODE",query['MODE']);//output MODE:p
        });
      }
    }
    

    您还可以查看工作解决方案here in stackblitz

    【讨论】:

      【解决方案3】:

      通过订阅阅读

      import { ActivatedRoute } from '@angular/router';
      
      @Component({
        selector: 'app-user-detail',
        templateUrl: 'user-detail.component.html'
      })
      export class UserDetailComponent implements OnInit {
          constructor(private activeRoute: ActivatedRoute) {
          }
      
      ngOnInit() {
          this.activeRoute.queryParams.subscribe(queryParams => {
              // do something with the query params
          });
      
          this.activeRoute.params.subscribe(routeParams => {
              this.loadUserDetail(routeParams.id);
          });
      }
      

      肮脏的方式

      通过嵌套订阅者如下:

      ngOnInit() {
          // Nest them together and
          this.activeRoute.queryParams.subscribe(queryParams => {
              this.activeRoute.params.subscribe(routeParams => {
                  this.loadUserDetail(routeParams.id, queryParams.type);
              });
          });
      }
      

      或者您可能想编写一个不同的版本,即将这些嵌套回调移动到一个辅助函数,然后将另一个回调传递给它接受查询和路由参数,即

      ngOnInit() {
          this.readUrlParams((routeParams, queryParams) => {
              this.loadUserDetail(routeParams.id, queryParams.type);
          });
      }
      
      readUrlParams(callback) {
          // Nest them together and
          this.activeRoute.queryParams.subscribe(queryParams => {
              this.activeRoute.params.subscribe(routeParams => {
                  callback(routeParams, queryParams);
              });
          });
      }
      

      使用 RxJS

      RxJS 是一个非常强大的库,你可以通过几种不同的方式来实现它,但我最喜欢并发现自己使用最多的一个是使用 combineLatest 运算符,我们使用它来合并路由和查询参数并有一个observable 将我们两者都放在一个对象中。这是我们更新后的示例的样子

      import { ActivatedRoute } from '@angular/router';
      
      // Add the observable and combineLatest
      import { Observable } from 'rxjs/Observable';
      import 'rxjs/add/observable/combineLatest';
      
      @Component({
        selector: 'app-user-detail',
        templateUrl: 'user-detail.component.html'
      })
      export class UserDetailComponent implements OnInit {
          constructor(private activeRoute: ActivatedRoute) {
          }
      
          ngOnInit() {
              // Combine them both into a single observable
              const urlParams = Observable.combineLatest(
                this.activatedRoute.params,
                this.activatedRoute.queryParams,
                (params, queryParams) => ({ ...params, ...queryParams})
              );
      
              // Subscribe to the single observable, giving us both
              urlParams.subscribe(routeParams => {
                  // routeParams containing both the query and route params
                  this.loadUserDetail(routeParams.id, routeParams.type);
              });
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-03
        • 2018-01-04
        • 1970-01-01
        • 2016-10-12
        • 2011-01-09
        • 2013-09-10
        • 1970-01-01
        相关资源
        最近更新 更多