Angular 5: 允许路由中的尾部斜杠

8
我正在使用Angular更新一个旧网站,并且我必须满足的要求之一是所有路由应该保持与原来相同(出于SEO目的)。
许多旧网站的路由以斜杠结尾(如/my/route/),其中一些以.html结尾,如/my/route.html
问题在于,routerLink会删除每个以斜杠结尾的路由中的最后一个斜杠(我的路由现在是/my/route)。
我该如何让routerLink保留末尾的斜杠?
这里可以看到一个简单的示例:AngularTrailingSlash

你说的许多路由以/或.html结尾是什么意思?我们在谈论哪些路由? - YounesM
我正在使用Angular更新旧网站的路由。出于明显的SEO原因,我希望在新网站上保留相同的路由。 - Marc Brillault
你能不能只是使用301重定向? - David
自2016年7月起,Google不再对301重定向进行惩罚,因此您可以真正考虑使用301方式,这种方式比其他选项更加清洁。 - gmazzotti
@gmazzoti你有参考来源吗?我的内部SEO经理似乎不同意你的观点。 - Marc Brillault
显示剩余2条评论
5个回答

5

我已经将以下内容添加到您的app.module.ts中:

import {Location, PathLocationStrategy} from '@angular/common';


const _orig_prepareExternalUrl = PathLocationStrategy.prototype.prepareExternalUrl;

PathLocationStrategy.prototype.prepareExternalUrl = function(internal) {
  const url = _orig_prepareExternalUrl.call(this, internal);

  if (url === '') {
    return url;
  }

  console.log('For ' + internal + ' we generated ' + url);
  if (url.endsWith('.html')) {
      return url;
  }

  if (url.endsWith('/')) {
    return url;
  }


  return url + '/';

};

Location.stripTrailingSlash = function (url) {
    const /** @type {?} */ match = url.match(/#|\?|$/);
    const /** @type {?} */ pathEndIdx = match && match.index || url.length;
    const /** @type {?} */ droppedSlashIdx = pathEndIdx - (url[pathEndIdx - 1] === '/' ? 1 : 0);
    const first = url.slice(0, droppedSlashIdx);
    const last = url.slice(pathEndIdx);

    if (first.endsWith('.html')) {
        return first + last;
    }

    return first + '/' + last;

};

现在,当 .html 不存在时,我加上了一个尾随斜杠,它可以正常工作。


@MarcBrillault,我有一个可能的解决方案,但我认为你的项目存在一些错误。当我点击链接时,我会收到“错误:未捕获(在承诺中):TypeError:无法读取null的属性'component'”。你能先在你的git仓库中修复这个问题吗? - Tarun Lalwani
@MarcBrillault,我已经添加了更改。URL现在没问题了,但你的导航问题仍然存在。 - Tarun Lalwani
非常抱歉耽搁了。您的答案可行,谢谢! - Marc Brillault
@TarunLalwani 我已经使用了上面的代码,它运行得很好。但是当我刷新页面时,它会出现错误:无法匹配任何路由。你能否给我提供一些建议? - Darshana
抱歉 @Darshana,代码自那时以来已经更新了很多,我无法回答你的问题。 - Marc Brillault
显示剩余4条评论

2
更进一步改进的代码(基于Umesh的代码)。
main.ts的基础上添加:
import { Location } from "@angular/common";
// Prevent stripping of trailing slash
Location.stripTrailingSlash = function stripTrailingSlashNew(url: string) {
  return url;
};

2

以下代码适用于我:

export const contactUsRoutes: Routes = [
    {
        path: 'contact-us/.', component: ContactUsComponent
    }
];

. .

<a [routerLink]="['/contact-us/.']">Contact us</a>

在你的 main.ts 文件中添加以下代码:

并在下面的代码中加入:

import { Location } from '@angular/common';

const __stripTrailingSlash = (Location as any).stripTrailingSlash;
(Location as any).stripTrailingSlash = function _stripTrailingSlash(url: string): string {
  const queryString$ = url.match(/([^?]*)?(.*)/);
  if (queryString$[2].length > 0) {
    return /[^\/]\/$/.test(queryString$[1]) ? queryString$[1] + '.' + queryString$[2] : __stripTrailingSlash(url);
  }
  return /[^\/]\/$/.test(url) ? url + '.' : __stripTrailingSlash(url);
};

我参考了以下链接来解决这个问题:

https://stackblitz.com/github/ssatz/Angular5-Preserve-Trailing-Slash

。最初的回答已经提供,您可以参考该链接来解决问题。

如果我需要保留URL中间的斜杠,有什么可能性? - Ajarudin Gunga

0
将以下代码添加到 main.ts 文件中,以保留路由链接中的尾部斜杠。
import { Location } from '@angular/common';
const __stripTrailingSlash = (Location as any).stripTrailingSlash;
(Location as any).stripTrailingSlash = function _stripTrailingSlash(url: string): string {
  return /[^\/]\/$/.test(url) ? url : __stripTrailingSlash(url);
}

// import main ng module
// bootstrap on document ready

为什么要用Location as any - edwin
1
此代码不支持像 path/?params 这样的 URL 参数。 - edwin

0
尝试在AppModule中使用继承Location类的方式,就像这样:

app.module.ts:

import { Injectable } from '@angular/core';
import { Location } from '@angular/common';

@Injectable()
export class UnstripTrailingSlashLocation extends Location {
  public static stripTrailingSlash(url: string): string {
    return url;
  }
}
Location.stripTrailingSlash = UnstripTrailingSlashLocation.stripTrailingSlash;

@NgModule({
            ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接