我在浏览器中有一个像这样的查询字符串
https://application.com/loader/?orderNumber=313Q&tracerId=PLM5689
。
我想保持查询中的键不区分大小写,即如果
ORDERNUMBER=313Q
和 TrAcErid=PLM5689
或
ordernumber=313Q
和 tracerid=PLM5689
仍然会以同样的方式工作。
到目前为止,我正在使用一种解决方法,通过迭代
params.keys
并基本上检查它是否与我的参数匹配。
this.activatedRoute.queryParamMap.subscribe(params => {
params.keys.forEach(key => {
if (key.toLowerCase() === 'ordernumber') {
this.ordernumber= params.get(key);
}
if (key.toLowerCase() === 'tracerid') {
this.tracerid= params.get(key);
}
});
});
是否有更好的方法来处理这个问题或某种使用查询字符串的最佳实践。我预计我的应用程序中会经常需要这个。
虽然这有效,但感觉像是一种很奇怪的方法。 我发现一些帖子建议查询字符串中的参数区分大小写,但我似乎并不理解它。
RFC 3986:https://www.rfc-editor.org/rfc/rfc3986#section-6.2.3
还有这个https://webmasters.stackexchange.com/questions/90339/why-are-urls-case-sensitive
在仔细阅读互联网并没有找到令人满意的解决方案后,我编写了自己的可重用类,该类包装了内置
Params
对象,并提供对查询字符串参数的不区分大小写的访问。
您可以在组件中使用它,例如:
import { ActivatedRoute } from '@angular/router';
import { CaseInsensitiveParamMap } from '../case-insensitive-param-map';
constructor(private activatedRoute: ActivatedRoute) {}
ngOnInit(): void {
this.activatedRoute.queryParams
.subscribe((params) => this.handleQueryParamsChanged(new CaseInsensitiveParamMap(params)));
}
private handleQueryParamsChanged(paramMap: CaseInsensitiveParamMap): void {
const returnUrl = paramMap.get('returnUrl');
// Returns the value of the first query param named 'returnUrl' case-insensitively
// See the test suite below for more examples
}
请注意,我还添加了一个
getNumber
辅助方法,可以更轻松地解析数字查询参数。如果该值不是数字或不存在,则返回 null
。
这是课程:
case-insensitive-param-map.ts
import { ParamMap, Params } from '@angular/router';
export class CaseInsensitiveParamMap implements ParamMap {
private params: Params;
constructor(params: Params) {
this.params = params || {};
}
has(name: string): boolean {
return Object.keys(this.params).some((key) => key.toLowerCase() === name.toLowerCase());
}
private getKeysCaseInsensitively(name: string): string[] {
return Object.keys(this.params).filter((key) => key.toLowerCase() === name.toLowerCase());
}
get(name: string): string | null {
if (this.has(name)) {
const keys = this.getKeysCaseInsensitively(name);
const v = this.params[keys[0]];
return Array.isArray(v) ? v[0] : v;
}
return null;
}
getNumber(name: string): number | null {
const v = this.get(name);
return !v || isNaN(Number(v)) ? null : Number(v);
}
getAll(name: string): string[] {
if (this.has(name)) {
const result: string[] = [];
this.getKeysCaseInsensitively(name).forEach((key) => {
const v = this.params[key];
result.push(...(Array.isArray(v) ? v : [v]));
});
return result;
}
return [];
}
get keys(): string[] {
return Object.keys(this.params);
}
}
以下是概述行为并用作文档的测试:
case-insensitive-param-map.spec.ts
import { Params } from '@angular/router';
import { CaseInsensitiveParamMap } from './case-insensitive-param-map';
describe('CaseInsensitiveParamMap', () => {
it('should return whether a case-insensitive parameter is present', () => {
const params: Params = { single: 's', multiple: ['m1', 'm2'] };
const map: CaseInsensitiveParamMap = new CaseInsensitiveParamMap(params);
expect(map.has('single')).toEqual(true);
expect(map.has('SINGLE')).toEqual(true);
expect(map.has('multiple')).toEqual(true);
expect(map.has('MULTIPLE')).toEqual(true);
expect(map.has('not here')).toEqual(false);
});
it('should return the keys of the parameters', () => {
const params: Params = { single: 's', multiple: ['m1', 'm2'] };
const map: CaseInsensitiveParamMap = new CaseInsensitiveParamMap(params);
expect(map.keys).toEqual(['single', 'multiple']);
});
it('should support single valued parameters', () => {
const params: Params = { single: 's', multiple: ['m1', 'm2'] };
const map: CaseInsensitiveParamMap = new CaseInsensitiveParamMap(params);
expect(map.get('single')).toEqual('s');
expect(map.get('multiple')).toEqual('m1');
});
it('should get numeric query string values as numbers', () => {
const params: Params = { single: '1', multiple: ['2', '3'], nonnumeric: 'foo', empty: '', zero: '0', nullProp: null, undefinedProp: undefined };
const map: CaseInsensitiveParamMap = new CaseInsensitiveParamMap(params);
expect(map.getNumber('single')).toEqual(1);
expect(map.getNumber('multiple')).toEqual(2);
expect(map.getNumber('zero')).toEqual(0);
expect(map.getNumber('nullProp')).toEqual(null);
expect(map.getNumber('undefinedProp')).toEqual(null);
expect(map.getNumber('nonnumeric')).toEqual(null);
expect(map.getNumber('not here')).toEqual(null);
expect(map.getNumber('empty')).toEqual(null);
});
it('should support case-insensitive single valued parameters', () => {
const params: Params = { SINGLE: 'S', MULTIPLE: ['M1', 'M2'] };
const map: CaseInsensitiveParamMap = new CaseInsensitiveParamMap(params);
expect(map.get('single')).toEqual('S');
expect(map.get('SINGLE')).toEqual('S');
expect(map.get('Single')).toEqual('S');
expect(map.get('multiple')).toEqual('M1');
expect(map.get('MULTIPLE')).toEqual('M1');
expect(map.get('Multiple')).toEqual('M1');
});
it('should support multiple valued parameters', () => {
const params: Params = { single: 's', multiple: ['m1', 'm2'] };
const map: CaseInsensitiveParamMap = new CaseInsensitiveParamMap(params);
expect(map.getAll('single')).toEqual(['s']);
expect(map.getAll('multiple')).toEqual(['m1', 'm2']);
});
it('should support case-insensitive multiple valued parameters', () => {
const params: Params = { SINGLE: 'S', MULTIPLE: ['M1', 'M2'], multiple: ['M3'] };
const map: CaseInsensitiveParamMap = new CaseInsensitiveParamMap(params);
expect(map.getAll('single')).toEqual(['S']);
expect(map.getAll('multiple')).toEqual(['M1', 'M2', 'M3']);
});
it('should return null when a single valued element is absent', () => {
expect(new CaseInsensitiveParamMap({}).get('not here')).toEqual(null);
});
it('should return [] when a multiple valued element is absent', () => {
expect(new CaseInsensitiveParamMap({}).getAll('not here')).toEqual([]);
});
});