允许 Angular 4 条路由在 URL 中传递特殊字符
Allowing Angular 4 routes to pass special characters in URL
我想做什么
我正在尝试在我的应用程序中创建一个路由,我希望管理员可以在其中输入 url 作为
http://localhost:4200/#/start/referral_code=jk
然后获取 referral_code
的值,即组件内部的 jk
。
在我的路线中,我将路线定义为
{ path: 'start/:referral_code', component: StartPageComponent },
我想要实现的是,当管理员输入上面提供的 URL
时,变量 referral_code
的值应该在指定的组件 StartPageComponent
中接收。
我在ngOnInit()
里面添加了如下
this.activatedRoute.params.subscribe((params: any) => {
if (params) {
let refCode = params.referral_code;
console.log(refCode);
}
});
实际发生了什么
一旦我输入上面的 URL
,=
之后的部分将与 =
一起删除,结果 url 将更改为
http://localhost:4200/#/start/referral_code
并且在组件内部 console.log(refCode);
显示字符串 referral_code
而不是 referral_code
的值,即 jk
.
限制
我不能像http://localhost:4200/#/start?referral_code=jk
那样使用QueryParams
,我也不能改变urlhttp://localhost:4200/#/start/referral_code=jk
感谢任何帮助。
您可以覆盖 Angular 的 DefaultUrlSerializer。
import {BrowserModule} from '@angular/platform-browser';
import {Injectable, NgModule} from '@angular/core';
import {AppComponent} from './app.component';
import {DefaultUrlSerializer, RouterModule, Routes, UrlSegment, UrlSerializer, UrlTree} from '@angular/router';
import {RouteTestComponent} from './route-test/route-test.component';
@Injectable()
export class CustomUrlSerializer implements UrlSerializer {
/** Parses a url into a {@link UrlTree} */
private defaultSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();
/** Parses a url into a {@link UrlTree} */
parse(url: string): UrlTree {
// This is the custom patch where you'll collect segment containing '='
const lastSlashIndex = url.lastIndexOf('/'), equalSignIndex = url.indexOf('=', lastSlashIndex);
if (equalSignIndex > -1) { // url contians '=', apply patch
const keyValArr = url.substr(lastSlashIndex + 1).split('=');
const urlTree = this.defaultSerializer.parse(url);
// Once you have serialized urlTree, you have two options to capture '=' part
// Method 1. replace desired segment with whole "key=val" as segment
urlTree.root.children['primary'].segments.forEach((segment: UrlSegment) => {
if (segment.path === keyValArr[0]) {
segment.path = keyValArr.join('='); // Suggestion: you can use other unique set of characters here too e.g. '$$$'
}
});
// Method 2. This is the second method, insert a custom query parameter
// urlTree.queryParams[keyValArr[0]] = keyValArr[1];
return urlTree;
} else {
// return as usual
return this.defaultSerializer.parse(url);
}
}
/** Converts a {@link UrlTree} into a url */
serialize(tree: UrlTree): string {
return this.defaultSerializer.serialize(tree);
}
}
const appRoutes: Routes = [
{
path: 'start/:referral_code',
component: RouteTestComponent
}
];
@NgModule({
declarations: [
AppComponent,
RouteTestComponent
],
imports: [
RouterModule.forRoot(appRoutes, {useHash: true}),
BrowserModule
],
providers: [
{
provide: UrlSerializer,
useClass: CustomUrlSerializer
}
],
bootstrap: [AppComponent]
})
export class AppModule {
}
组件内部
this.route.params.subscribe(params => {
console.log(params['referral_code']); // prints: referral_code=jk
});
// url http://localhost:4200/#/start/referral_code=jk will be changed to http://localhost:4200/#/start/referral_code%3Djk
或者如果您更喜欢上面的方法 2,请使用:
this.route.queryParams.subscribe(queryParams => {
console.log(queryParams['referral_code']); // prints: jk
});
// url http://localhost:4200/#/start/referral_code=jk will be changed to http://localhost:4200/#/start/referral_code?referral_code=jk
我想做什么
我正在尝试在我的应用程序中创建一个路由,我希望管理员可以在其中输入 url 作为
http://localhost:4200/#/start/referral_code=jk
然后获取 referral_code
的值,即组件内部的 jk
。
在我的路线中,我将路线定义为
{ path: 'start/:referral_code', component: StartPageComponent },
我想要实现的是,当管理员输入上面提供的 URL
时,变量 referral_code
的值应该在指定的组件 StartPageComponent
中接收。
我在ngOnInit()
里面添加了如下
this.activatedRoute.params.subscribe((params: any) => {
if (params) {
let refCode = params.referral_code;
console.log(refCode);
}
});
实际发生了什么
一旦我输入上面的 URL
,=
之后的部分将与 =
一起删除,结果 url 将更改为
http://localhost:4200/#/start/referral_code
并且在组件内部 console.log(refCode);
显示字符串 referral_code
而不是 referral_code
的值,即 jk
.
限制
我不能像http://localhost:4200/#/start?referral_code=jk
那样使用QueryParams
,我也不能改变urlhttp://localhost:4200/#/start/referral_code=jk
感谢任何帮助。
您可以覆盖 Angular 的 DefaultUrlSerializer。
import {BrowserModule} from '@angular/platform-browser';
import {Injectable, NgModule} from '@angular/core';
import {AppComponent} from './app.component';
import {DefaultUrlSerializer, RouterModule, Routes, UrlSegment, UrlSerializer, UrlTree} from '@angular/router';
import {RouteTestComponent} from './route-test/route-test.component';
@Injectable()
export class CustomUrlSerializer implements UrlSerializer {
/** Parses a url into a {@link UrlTree} */
private defaultSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();
/** Parses a url into a {@link UrlTree} */
parse(url: string): UrlTree {
// This is the custom patch where you'll collect segment containing '='
const lastSlashIndex = url.lastIndexOf('/'), equalSignIndex = url.indexOf('=', lastSlashIndex);
if (equalSignIndex > -1) { // url contians '=', apply patch
const keyValArr = url.substr(lastSlashIndex + 1).split('=');
const urlTree = this.defaultSerializer.parse(url);
// Once you have serialized urlTree, you have two options to capture '=' part
// Method 1. replace desired segment with whole "key=val" as segment
urlTree.root.children['primary'].segments.forEach((segment: UrlSegment) => {
if (segment.path === keyValArr[0]) {
segment.path = keyValArr.join('='); // Suggestion: you can use other unique set of characters here too e.g. '$$$'
}
});
// Method 2. This is the second method, insert a custom query parameter
// urlTree.queryParams[keyValArr[0]] = keyValArr[1];
return urlTree;
} else {
// return as usual
return this.defaultSerializer.parse(url);
}
}
/** Converts a {@link UrlTree} into a url */
serialize(tree: UrlTree): string {
return this.defaultSerializer.serialize(tree);
}
}
const appRoutes: Routes = [
{
path: 'start/:referral_code',
component: RouteTestComponent
}
];
@NgModule({
declarations: [
AppComponent,
RouteTestComponent
],
imports: [
RouterModule.forRoot(appRoutes, {useHash: true}),
BrowserModule
],
providers: [
{
provide: UrlSerializer,
useClass: CustomUrlSerializer
}
],
bootstrap: [AppComponent]
})
export class AppModule {
}
组件内部
this.route.params.subscribe(params => {
console.log(params['referral_code']); // prints: referral_code=jk
});
// url http://localhost:4200/#/start/referral_code=jk will be changed to http://localhost:4200/#/start/referral_code%3Djk
或者如果您更喜欢上面的方法 2,请使用:
this.route.queryParams.subscribe(queryParams => {
console.log(queryParams['referral_code']); // prints: jk
});
// url http://localhost:4200/#/start/referral_code=jk will be changed to http://localhost:4200/#/start/referral_code?referral_code=jk