【问题标题】:Angular routing for prefix with route parameter带有路由参数的前缀的角度路由
【发布时间】:2022-01-06 10:54:40
【问题描述】:

我想实现用户个人资料页面。只需使用

/profile/user123 路径使用:

app-routing.module

{
  path: 'profile',
  loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
},

profile-routing.module

{
  path: ':username',
  component: ProfileComponent
},

但是,我想做一些花哨的 URL,例如 /@user123

不幸的是,我没有找到任何关于如何做到这一点的线索。我尝试了以下方法:

app-routing.module

{
  path: '@:username',
  loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
},

profile-routing.module

{
  path: '',
  component: ProfileComponent
},

但是没有用。

我想到的只有一件事,那就是使用 Guard 检查“@”前缀,否则重定向到 /not-found 页面。

关于如何使用“Angular”方式进行路由的任何想法?

【问题讨论】:

    标签: angular typescript routes router prefix


    【解决方案1】:

    您可以使用自定义路由matcher 来达到预期的效果。

    • app-routing.module.ts
        {
          path: 'profile',
          loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
        },
    
    • profile-routing.module.ts 中,您可以通过提供 custom URL-matching function 来指定路由:
        {
          matcher: (url) => {
            // You can have regex as per your requirement
            if (url.length === 1 && url[0].path.match(/^@[\w]+$/gm)) {
              return {
                consumed: url,
                posParams: {
                  username: new UrlSegment(url[0].path.substr(1), {}) // <--- creating UrlSegment by getting rid of @ from url path
                }
              };
            }
        
            return null;
          },
          component: ProfileComponent
        }
    
    • profile.component.ts 文件中,您可以将username 读取为:
        username$!: Observable<string | null>;
        constructor(private activatedRoute: ActivatedRoute) { }
    
        ngOnInit(): void {
          this.username$ = this.activatedRoute.paramMap
            .pipe(
              map((params: ParamMap) => params.get('username'))
            );
        }
    
    • profile.component.html 中,您可以将用户名打印为:
        <p>
            Profile: {{username$ | async}}
        </p>
    
    • 现在只需导航到 url /profile/@user123,您应该能够在 ProfileComponent 中将 user123 作为用户名

    【讨论】:

    • 这个解决方案做了一点调整,因为我想做/@user123,而不是/profile/@user123。另外,我在正则表达式中添加了连字符。我将发布修改后的解决方案,但我接受了您的回答。谢谢
    【解决方案2】:

    Siddhant 提供的解决方案非常好,但我想要/@user123 而不是/profile/@user123,所以我稍微调整了一下。

    app-routing.module.ts

    {
      matcher: (url) => {
        if (url.length === 1 && url[0].path.match(/^@[\w.\-]+$/gm)) { // <--- added a hyphen and a dot, since \w only does [a-zA-Z0-9_]
          return {
            consumed: url,
            posParams: {
              username: new UrlSegment(url[0].path.substr(1), {}) // <--- creating UrlSegment by getting rid of @ from url path
            }
          };
        }
        return null;
      },
      loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
    },
    

    profile.routing.module.ts

    {
      path: '',
      component: ProfileComponent
    },
    

    profile.component.ts

    ngOnInit(): void {
      this.activatedRoute.paramMap.subscribe(paramMap => {
        this.userService.getUser(paramMap.get('username')).subscribe(res => {
          if (res) {
            this.user = res;
          } else {
            this.router.navigate([Utils.ARTICLE_NOT_FOUND_URL]);
          }
        });
      });
    }
    

    【讨论】:

      【解决方案3】:

      我正在添加另一个答案,因为我还需要使用 @user123/edit 路径,但它不适用于原始解决方案。所以这里是如何做到的:

      app-routing.module.ts

       {
          matcher: (url) => {
            console.log(url);
            if (url[0].path.match(/^@[\w.\-]+$/gm)) { <-- removed check for url length
              return {
                consumed: url.slice(0, 1), <-- return the rest of the URL instead of the whole URL (this routing rule should only consume @user123 and return the rest of the URL, which is /edit)
                posParams: {
                  username: new UrlSegment(url[0].path.substr(1), {}) // <--- creating UrlSegment by getting rid of @ from url path
                }
              };
            }
            return null;
          },
          loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
        },
      

      profile.routing.module.ts

      {
          path: '',
          component: ProfileComponent
        },
        {
          path: 'edit',
          component: EditProfileComponent
        },
      

      【讨论】:

        猜你喜欢
        • 2020-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多