使用Angular 2路由器的网址自定义编码(使用+符号代替空格)

时间:2016-09-16 23:01:59

标签: angular angular2-routing

我正在使用Angular 2路由器来更新搜索应用程序的URL中的查询参数。我试图用+符号替换查询中的空格。但是,+符号正在编码。例如:

this.router.navigatebyUrl('?q=one+two');

使用“?q = 1%2Btwo”填充网址。

在查看Angular 2的源代码时,路由器似乎将URL转换为UrlTree which uses encodeURIComponent() to encode the url。因此,无法阻止默认编码。

我目前的流程是通过如上所示执行navigateByUrl来更改路径,然后通过以下方式侦听更改:

this.routeSubscription = this.route.queryParams.subscribe((params: any) => {
  this.term = (params.q ? params.q : '');
});

是否有另一种处理查询参数的方法可以让我使用自己的策略进行网址编码?

3 个答案:

答案 0 :(得分:18)

我能够找到解决问题的方法。您可以通过实现UrlSerializer类来创建自己的自定义URL序列化程序。

自定义网址序列化工具

像这样创建自定义网址序列化程序:

class CustomUrlSerializer implements UrlSerializer {
    parse(url: string): UrlTree {
        // Custom code here
    }

    serialize(tree: UrlTree): string {
        // Custom code here
    }
}

然后,您只需要提供CustomUrlSerializer来代替UrlSerializer,您可以在导入两个序列化程序后将其放置在AppModule提供程序数组中。

providers: [
    { provide: UrlSerializer, useClass: CustomUrlSerializer },
    ...
]

现在,当您调用router.navigate或router.navigateByUrl时,它将使用您的自定义序列化程序进行解析和序列化。

使用+符号作为空格

将+符号解析为空格:

parse(url: string): UrlTree {
    // Change plus signs to encoded spaces
    url = url.replace(/\+/g, '%20');
    // Use the default serializer that you can import to just do the 
    // default parsing now that you have fixed the url.
    return this.defaultUrlSerializer.parse(url)  
}

用于序列化:

serialize(tree: UrlTree): string {
    // Use the default serializer to create a url and replace any spaces with + signs
    return this.defaultSerializer.serialize(tree).replace(/%20/g, '+');
}

DefaultUrlSerializer

答案 1 :(得分:2)

我遇到了指定自定义提供程序的问题。显然,使用--prod标志进行编译时存在循环依赖关系,导致文本出现错误:useClass cannot by null.这就是我解决该错误的方法:

在AppModule中,定义以下内容:

const customUrlSerializer = new CustomUrlSerializer();
const CustomUrlSerializerProvider = {
    provide: UrlSerializer,
    useValue: customUrlSerializer
};

然后在providers数组中,添加上面指定的提供程序。

...
providers: [CustomUrlSerializerProvider]
...

答案 2 :(得分:0)

我尝试在Angular 9.1中使用@Noahs解决方案,以避免将?替换为%3F

但是,此无效

class CustomUrlSerializer implements UrlSerializer {
  parse(url: string): UrlTree {
    return this.defaultSerializer.parse(url)  
  }

  serialize(tree: UrlTree): string {
    return this.defaultSerializer.serialize(tree).replace(/%3F/g, '?');
  }
}

Angular抱怨以下错误消息

client:159 src/app/app.module.ts:36:17 - error TS2339: Property 'defaultSerializer' does not exist on type 'CustomUrlSerializer'.

不过,以下代码为我工作了

class CustomUrlSerializer extends DefaultUrlSerializer {
  parse(url: string): UrlTree {
    return super.parse(url)  
  }

  serialize(tree: UrlTree): string {
    return super.serialize(tree).replace(/%20/g, '+');
  }
}

在那里,我已替换:

implements UrlSerializer --> extends DefaultUrlSerializer
this.defaultSerializer   --> super

注意:我删除了以下反向翻译,因为它在路由URL之前将?替换为%3F,但是在这种情况下,我们希望保留它:

  parse(url: string): UrlTree {
    url = url.replace(/\?/g, '%3F'); // <--- removed
    ...