簡體   English   中英

Angular 2 可選路由參數

[英]Angular 2 optional route parameter

在 Angular 2 路由中是否可以有一個可選的路由參數? 我在 RouteConfig 中嘗試了 Angular 1.x 語法,但收到以下錯誤:

“原始異常:路徑“/user/:id?”包含“?”,這在路由配置中是不允許的。”

@RouteConfig([
{
    path: '/user/:id?',
    component: User,
    as: 'User'
}])

您可以使用和不使用參數定義多個路由:

@RouteConfig([
    { path: '/user/:id', component: User, name: 'User' },
    { path: '/user', component: User, name: 'Usernew' }
])

並處理組件中的可選參數:

constructor(params: RouteParams) {
    var paramId = params.get("id");

    if (paramId) {
        ...
    }
}

另請參閱相關的 github 問題: https : //github.com/angular/angular/issues/3525

{path: 'users', redirectTo: 'users/', pathMatch: 'full'},
{path: 'users/:userId', component: UserComponent}

這樣,當添加參數時組件不會重新渲染。

當信息是可選的時,建議使用查詢參數。

路由參數還是查詢參數?

沒有硬性規定。 一般來說,

更喜歡路由參數時

  • 該值是必需的。
  • 該值對於區分一條路由路徑和另一條路由路徑是必要的。

更喜歡查詢參數時

  • 該值是可選的。
  • 該值是復雜的和/或多變量的。

來自https://angular.io/guide/router#optional-route-parameters

您只需要從路由路徑中取出參數即可。

@RouteConfig([
{
    path: '/user/',
    component: User,
    as: 'User'
}])

Angular 4 - 解決可選參數排序的解決方案:

做這個:

const appRoutes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'products', component: ProductsComponent},
  {path: 'products/:id', component: ProductsComponent}
]

請注意, productsproducts/:id路由的名稱完全相同。 Angular 4 將正確跟蹤沒有參數的路由的products ,如果有參數,它將遵循products/:id

但是,非參數路由products的路徑不能有尾部斜杠,否則 angular 會錯誤地將其視為參數路徑。 所以就我而言,我有產品的尾隨斜線,但它不起作用。

不要這樣做:

...
{path: 'products/', component: ProductsComponent},
{path: 'products/:id', component: ProductsComponent},
...

rerezz 的回答非常好,但它有一個嚴重的缺陷。 它會導致User組件重新運行ngOnInit方法。

當您在那里執行一些繁重的工作並且在從非參數路由切換到參數路由時不希望它重新運行時,這可能會出現問題。 盡管這兩條路由旨在模仿可選的 url 參數,但不會成為 2 條獨立的路由。

以下是我解決問題的建議:

const routes = [
  {
    path: '/user',
    component: User,
    children: [
      { path: ':id', component: UserWithParam, name: 'Usernew' }
    ]
  }
];

然后,您可以將負責處理參數的邏輯移至UserWithParam組件,而將基本邏輯留在User組件中。 當您從/user導航到/user/123時,無論您在User::ngOnInit做什么都不會再次運行。

不要忘記將<router-outlet></router-outlet>放在User的模板中。

此處建議的答案,包括rerezz接受的答案,建議添加多個路由條目工作正常。

然而,當在路由條目之間,即在帶有參數的路由條目和沒有參數的條目之間進行更改時,將重新創建組件。

如果你想避免這種情況,你可以創建自己的路由匹配器來匹配兩條路由:

export function userPageMatcher(segments: UrlSegment[]): UrlMatchResult {
    if (segments.length > 0 && segments[0].path === 'user') {
        if (segments.length === 1) {
            return {
                consumed: segments,
                posParams: {},
            };
        }
        if (segments.length === 2) {
            return {
                consumed: segments,
                posParams: { id: segments[1] },
            };
        }
        return <UrlMatchResult>(null as any);
    }
    return <UrlMatchResult>(null as any);
 }

然后在路由配置中使用匹配器:

const routes: Routes = [
    {
        matcher: userPageMatcher,
        component: User,
    }
];

使用 angular4,我們只需要在層次結構中將路由組織在一起

const appRoutes: Routes = [
  { 
    path: '', 
    component: MainPageComponent 
  },
  { 
    path: 'car/details', 
    component: CarDetailsComponent 
  },
  { 
    path: 'car/details/platforms-products', 
    component: CarProductsComponent 
  },
  { 
    path: 'car/details/:id', 
    component: CadDetailsComponent 
  },
  { 
    path: 'car/details/:id/platforms-products', 
    component: CarProductsComponent 
  }
];

這對我有用。 這樣路由器就可以根據選項 id 參數知道下一條路由是什么。

有三種方法可以通過路由將路由參數從一個組件發送到另一個組件。 但首先將這些庫導入組件 related.ts 文件並在構造函數中定義

private route: ActivatedRoute
private router: Router

第一種方式:必需的路由參數

//Route Configuration
{path: 'user/:id', component: UserDetailComponent}

//Set Hyperlink/routerLink
<a [routerLink]="['/user', user.id]"></a> 

 //Requesting Url after click on hyperlink
 http://localhost:4200/user/6

//Now you can read id value in navigated component
this.route.snapshot.paramMap.get('id');

第二種方式:可選路徑參數

//Route Configuration
    {path: 'user', component: UserDetailComponent}
    
    //Set Hyperlink/routerLink
    <a [routerLink]=['/user', {name: userName, status: true}]"></a>


//Requesting Url after click on hyperlink
    http://localhost:4200/user;name:userNameValue;status:true

//Now you can read values in navigated component
    this.route.snapshot.paramMap.get('userId');
    this.route.snapshot.paramMap.get('userName');

第三種方式:可選路徑參數

//Route Configuration
    {path: 'user', component: UserDetailComponent}
    
    //Set Hyperlink/routerLink
    <a [routerLink]="['/user']"  [queryParms]="{userId:'911', status:true}"></a>

    //Requesting Url after click on hyperlink
    http://localhost:4200/user?userId=911&status=true

    
    //Now you can read values in navigated component
    this.route.snapshot.paramMap.get('userId');
    this.route.snapshot.paramMap.get('userName');

參考: https://qastack.mx/programming/44864303/send-data-through-routing-paths-in-angular

遇到此問題的另一個實例,並在尋找解決方案時來到這里。 我的問題是我正在做孩子,以及組件的延遲加載以優化一些東西。 簡而言之,如果您懶惰加載父模塊。 主要是我在路由中使用了 '/:id',它抱怨 '/' 是它的一部分。 不是這里的確切問題,但它適用。

來自父級的應用程序路由

...
const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: 'pathOne',
        loadChildren: 'app/views/$MODULE_PATH.module#PathOneModule'
      },
      {
        path: 'pathTwo',
        loadChildren: 'app/views/$MODULE_PATH.module#PathTwoModule'
      },
...

子路由懶加載

...
const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: '',
        component: OverviewComponent
      },
      {
        path: ':id',
        component: DetailedComponent
      },
    ]
  }
];
...

使用此匹配器功能,您無需重新渲染組件即可獲得理想的行為。 當 url.length 等於 0 時,沒有可選參數,當 url.length 等於 1 時,有 1 個可選參數。 id - 是可選參數的名稱。

  const routes: Routes = [
  {
    matcher: (segments) => {
      if (segments.length <= 1) {
        return {
          consumed: segments,
          posParams: {
            id: new UrlSegment(segments[0]?.path || '', {}),
          },
        };
      }
      return null;
    },
    pathMatch: 'prefix',
    component: UserComponent,
  }]

在 Angular 8 中,您可以簡單地添加參數而無需更改您的路由器配置。

Angular Doc 可選參數

在 yourModule.routing.module.ts

const routes: Routes = [
  { path: 'somePath/:RequiredParam', component: Yourcomponent }
];

在您的模板中:

<div [RouterLink] = ['somePath', requiredParamValue, {optionalParam: value}]></div>

我無法評論,但參考: Angular 2 optional route parameter

Angular 6 的更新:

import {map} from "rxjs/operators"

constructor(route: ActivatedRoute) {
  let paramId = route.params.pipe(map(p => p.id));

  if (paramId) {
    ...
  }
}

有關 Angular6 路由的其他信息,請參閱https://angular.io/api/router/ActivatedRoute

面對與延遲加載類似的問題,我已經這樣做了:

const routes: Routes = [
  {
    path: 'users',
    redirectTo: 'users/',
    pathMatch: 'full'
  },
  {
    path: 'users',
    loadChildren: './users/users.module#UserssModule',
    runGuardsAndResolvers: 'always'
  },
[...]

然后在組件中:

  ngOnInit() {
    this.activatedRoute.paramMap.pipe(
      switchMap(
        (params: ParamMap) => {
          let id: string = params.get('id');
          if (id == "") {
            return of(undefined);
          }
          return this.usersService.getUser(Number(params.get('id')));
        }
      )
    ).subscribe(user => this.selectedUser = user);
  }

這邊走:

  • 沒有/的路由被重定向到有的路由。 由於pathMatch: 'full' ,只有這樣的特定完整路由被重定向。

  • 然后,接收到users/:id 如果實際路由是users/id"" ,所以在ngOnInit檢查它並采取相應的行動; 否則, id是 id 並繼續。

  • 作用於selectedUser的其余組件是否未定義(*ngIf 和類似的東西)。

Master Detail 視圖也有同樣的問題。 主視圖可以在沒有:elementId參數的情況下可見,但仍應在打開詳細信息選擇並在 url 中使用:elementId時顯示。

我是這樣解決的:

const routes: Routes = [
  {
    path: '',
    component: MasterDetailComponent,
    children: [
      {
        path: ':elementId',
        children: [
          {
            path: 'details',
            component: DetailComponent
          },
          {
            path: '',
            redirectTo: 'details'
          }
        ]
      }
    ]
  }
];

然后在 MasterDetailComponent (例如在 ngOnInit 方法中)您可以使用子路由獲取:elementId

const childRouteWithElementId = this.route.snapshot.children[0];
const elementIdFromUrl = childRouteWithElementId.params.elementId;
if (!!elementIdFromUrl ) {
  // Do what you need to with the optional parameter
}

當然,您可以在沒有子路由的情況下做同樣的事情,並且在 url 末尾只有可選的elementId

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM