Angular2:使路径路径不区分大小写

时间:2016-03-22 12:40:52

标签: angular angular2-routing

我有以下路由配置。

@RouteConfig([
    {
        path: '/home',
        name: 'Homepage',
        component: HomepageComponent,
        useAsDefault: true
    }
)
export class AppComponent {
}

每当浏览器指向/home时此路由有效,但不适用于/Home或任何其他案例变体。如何在不关心案例的情况下使路由器路由到组件。

感谢

8 个答案:

答案 0 :(得分:34)

这就是我的所作所为。

import { DefaultUrlSerializer, UrlTree } from '@angular/router';

export class LowerCaseUrlSerializer extends DefaultUrlSerializer {
    parse(url: string): UrlTree {
        // Optional Step: Do some stuff with the url if needed.

        // If you lower it in the optional step 
        // you don't need to use "toLowerCase" 
        // when you pass it down to the next function
        return super.parse(url.toLowerCase()); 
    }
}

@NgModule({
    imports: [
      ...
    ],
    declarations: [AppComponent],
    providers: [
        {
            provide: UrlSerializer,
            useClass: LowerCaseUrlSerializer
        }
    ],
    bootstrap: [AppComponent]
})

答案 1 :(得分:8)

<强>更新

这还没有进入新的路由器

<强>原始

最近推出了正则表达式匹配器。这可能对您的用例有所帮助。

请参阅https://github.com/angular/angular/pull/7332/files

来自Brandon Roberts的Plunker

@RouteConfig([
  { name : 'Test',
    //path : '/test',
    regex: '^(.+)/(.+)$', 
    serializer: (params) => new GeneratedUrl(`/${params.a}/${params.b}`, {c: params.c}),
    component: Test
//   useAsDefault: true
  }
])

答案 2 :(得分:7)

我在app.component.ts中执行了此操作:

export class AppComponent implements OnInit {
  constructor(private _route: Router) { }
  public ngOnInit() {
    this._route.events.subscribe(event => {
      if (event instanceof NavigationStart) {
        let url = (<NavigationStart>event).url;
        if (url !== url.toLowerCase()) {
          this._route.navigateByUrl((<NavigationStart>event).url.toLowerCase());
        }
      }
    });
  }
}

并且在路由器链接上需要这个以使其在选中时处于活动状态:

<a routerLink="/heroes" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: false }">Heroes</a>

答案 3 :(得分:7)

Timothy's answer的一点修复,它不会改变匹配的参数名称和值的大小写:

class A(object):
    a = "Hello"
    b = "World"

class B(A):
    pass

class C(B):
    pass

c = C()
print(c.a,c.b)

编辑:除了上面解释的问题之外,还有另一个微妙的错误,现在已经解决了。 for循环应该迭代import {Route, UrlSegment, UrlSegmentGroup} from '@angular/router'; export function caseInsensitiveMatcher(url: string) { return function( segments: UrlSegment[], segmentGroup: UrlSegmentGroup, route: Route ) { const matchSegments = url.split('/'); if ( matchSegments.length > segments.length || (matchSegments.length !== segments.length && route.pathMatch === 'full') ) { return null; } const consumed: UrlSegment[] = []; const posParams: {[name: string]: UrlSegment} = {}; for (let index = 0; index < matchSegments.length; ++index) { const segment = segments[index].toString().toLowerCase(); const matchSegment = matchSegments[index]; if (matchSegment.startsWith(':')) { posParams[matchSegment.slice(1)] = segments[index]; consumed.push(segments[index]); } else if (segment.toLowerCase() === matchSegment.toLowerCase()) { consumed.push(segments[index]); } else { return null; } } return { consumed, posParams }; }; } 而不是matchSegments

答案 4 :(得分:5)

注意:以下适用于Angular 4.x

我只使用匹配功能:

import { RouterModule, UrlSegment, UrlSegmentGroup, Route } from '@angular/router';

function CaseInsensitiveMatcher(url: string) {
    url = url.toLowerCase();

    return function(
        segments: UrlSegment[],
        segmentGroup: UrlSegmentGroup,
        route: Route
    ) {
        let matchSegments = url.split('/');
        if (
            matchSegments.length > segments.length ||
            (matchSegments.length !== segments.length && route.pathMatch === 'full')
        ) {
            return null;
        }

        let consumed: UrlSegment[] = [];
        let posParams: {[name: string]: UrlSegment} = {};
        for (let index = 0; index < segments.length; ++index) {
            let segment = segments[index].toString().toLowerCase();
            let matchSegment = matchSegments[index];

            if (matchSegment.startsWith(':')) {
                posParams[matchSegment.slice(1)] = segments[index];
                consumed.push(segments[index]);
            }
            else if (segment === matchSegment) {
                consumed.push(segments[index]);
            }
            else {
                return null;
            }
        }

        return { consumed, posParams };
    }
}

使用:

@NgModule({
    imports: [
        ...
        RouterModule.forRoot([
            { matcher: CaseInsensitiveMatcher('user/:id'), component: ProfileComponent },
        ])
    ],
    declarations: [
        ...
    ],
    bootstrap: [
        AppComponent
    ]
})

编辑:我刚刚发现,为了使用AoT编译,@ NgModule部分看起来更像是这样:

export function profileMatch() {
    return CaseInsensitiveMatcher('user/:id').apply(this, arguments);
}

@NgModule({
    imports: [
        ...
        RouterModule.forRoot([
            { matcher: profileMatch, component: ProfileComponent },
        ])
    ],
    declarations: [
        ...
    ],
    bootstrap: [
        AppComponent
    ]
})

答案 5 :(得分:2)

我对此问题的解决方法:

/* IMPORTS */

let routeEntries = [
    { path: '/home', component: HomePage }
    /* DEFAULT ROUTE */
    { path: '/', component: HomePage },
    /* NOT FOUND ROUTE */
    { path: '*', component: HomePage }
];

@Component(/* SETUP */)
@Routes(routeEntries)

export App implements OnInit {
    /* STUFF */
    ngOnInit() {
        // subscribe to router changes
        this.router.changes.forEach(() => {
            let routerLink = location.pathname;
            let routerLinkLower = routerLink.toLowerCase();
            // if the route does not exist, check for the lowercase version
            if (!routeEntries.find((route) => { return route.path === routerLink; })) {
                this.router.navigate([routerLinkLower]);
            }
            // if the route is correct, set the active page
            else {
                // do something here if required
            }
        });
    }
}

这适用于RC1路由器,并与路线变化相符,例如:

'{domain}:{port}/HoMe'
'{domain}:{port}/homE'
'{domain}:{port}/Home'
...

答案 6 :(得分:0)

这里是LowerCaseUrlSerializer的更新版本,不小写查询参数。

import { DefaultUrlSerializer, UrlTree } from '@angular/router';

export class LowerCaseUrlSerializer extends DefaultUrlSerializer {
    parse(url: string): UrlTree {
      const path = url.split('?')[0];
      const query = url.split('?')[1] || '';
      return super.parse(path.toLowerCase() + (query !== '' ? `?${query}`: ''));
    }
}

答案 7 :(得分:-4)

这就是我解决这个问题的方法

    { path: '/home', redirectTo: ['/Home'] },
    { path: '/Home', component: HomeComponent, name: 'Home' },