如何重定向到一个外部的 URL 从 angular2路由不使用组件?

我想创建一个外部重定向,但为了使所有路由一致,我认为在路由器国家配置下做所有事情(包括外部重定向)会很好。

所以:

const appRoutes: Routes = [
{path: '', component: HomeComponent},
{path: 'first', component: FirstComponent},
{path: 'second', component: SecondComponent},
{path: 'external-link', /*would like to have redirect here*/}
];

UPD : 我不想在这种情况下使用空组件@ koningdavid相似。这个解决方案对我来说真的很奇怪。对于这种情况,它应该是非常容易实现的,不需要虚拟组件。

145057 次浏览

据我所知,NG2路由器不支持外部重定向。您可以创建一个重定向组件作为工作区。

import { Component, OnInit } from '@angular/core';


@Component({
selector: 'redirect',
template: 'redirecting...'
})
export class RedirectComponent implements OnInit {
constructor() { }


ngOnInit() {
window.location.href = 'http://www.redirecturl.com'
}
}

然后把它用在你的路由上

{ path: 'login', component: RedirectComponent, pathmath: 'full'},

嗯..。

我认为你可以简单地请求网址,而不是调用 ng2路由器..。


比如说..。

<a href="http://example.com">External</a>

而不是

<a routerLink="/someRoute" routerLinkActive="active">External</a>

或者

window.location.href = 'http://www.example.com'

而不是

this.router.navigate( [ '/someRoute', 'someParam' ] );

对吧?

路由器不能对外重定向。外部资源不能是应用程序的状态。

如果只是为了清晰起见,将所有路由保持在一个点上可见,那么您可以定义另一个常量数组,其中所有外部路径与路由位于同一个文件中。

您可以使用路由的解决选项通过一个技巧来实现您想要的结果。Resolve 是 Angular2将为要初始化的路由获得的一些数据值。更多细节可以在官方文档中找到 给你

我已经尝试过这种方法,它确实有效。例如:

将其添加到提供程序部分(加上从 Routing 导入所需的类)

@NgModule({
providers: [
{
provide: 'externalUrlRedirectResolver',
useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) =>
{
window.location.href = (route.data as any).externalUrl;
}
}
]
})

然后你可以这样定义你的路线:

{
path: 'test',
component: AnyRandomComponent,
resolve: {
url: 'externalUrlRedirectResolver'
},
data: {
externalUrl: 'http://www.google.com'
}
}

这将重定向到外部 URL。真的有点像黑客。我试图在完全不使用组件的情况下实现结果,但是您必须使用 redirectTocomponentchildrenloadChildrenredirectTo不会触发决心,我不确定孩子,虽然你可以试验。

您可以在一个很好的类中实现它,而不是在提供程序中直接执行函数。文档中的更多信息(参见上面的参考文献)。

另外,我觉得我自己更愿意使用重定向组件。只需对数据使用这个技巧,并通过 externalUrl从路由器获取状态,就可以得到这个参数。

我假设您不想为每个 url 创建一个组件,这就是为什么您希望在没有组件的情况下创建组件..。

因此,您可以尝试创建一个函数,为您生成组件对象..。

比如说..。

function generateLinkingComponent( url ) {
// Generate your component using koningdavid's code
// replace 'http://www.redirecturl.com' with url param
// and return it...
}

然后像这样把它添加到你的路由器配置中..。

const appRoutes: Routes = [
{path: '', component: HomeComponent},
{path: 'first', component: FirstComponent},
{path: 'second', component: SecondComponent},
{path: 'external-link', component: generateLinkingComponent( 'http://example.com' )},
{path: 'client-login', component: generateLinkingComponent( 'http://client-login.example.com' )},
{path: 'admin-login', component: generateLinkingComponent( 'http://admin.example.com' )},
];

这将是很容易与 JS... 但不知道如何可以返回一个类在一个函数中的 typeScript..。

希望能帮上忙。

总结一下伊利亚的回答:

添加这个模块。

import { Component, Injectable, NgModule } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';


@Component({
template: ''
})
class ExternalLinkComponent {
constructor() {
}
}


@Injectable()
class ExternalLinkResolver implements Resolve<any> {
resolve(route: ActivatedRouteSnapshot): any {
window.location.href = route.data.targetUri;
return true;
}
}


export class ExternalRoute {
data: {
targetUri: string;
};
path: string;
pathMatch = 'full';
resolve = { link: ExternalLinkResolver };
component = ExternalLinkComponent;


constructor(path: string, targetUri: string) {
this.path = path;
this.data = { targetUri: targetUri };
}


}


@NgModule({
providers: [ ExternalLinkResolver ],
declarations: [ExternalLinkComponent]
})
export class ExternalRoutesModule { }

然后导入 ExternalRoutesModule并添加 ExternalRoute 的实例。

const childRoutes: Routes = [
new ExternalRoute('', '/settings/account'),
{ path: 'staff-profiles', component:  StaffProfilesComponent},
{ path: 'staff-assignments', component:  StaffAssignmentsComponent}
];


const routes: Routes = [
{ path: '', component: BaseComponent, children: childRoutes }
];


@NgModule({
imports: [ ExternalRoutesModule, RouterModule.forChild(routes) ],
exports: [ RouterModule ]
})
export class SettingsRoutingModule { }

注意,在这个例子中,我正在通过 loadChildren 挂载子模块路由。

您可以创建一个 RedirectGuard:

import {Injectable} from '@angular/core';
import {CanActivate, ActivatedRouteSnapshot, Router, RouterStateSnapshot} from '@angular/router';


@Injectable({
providedIn: 'root'
})
export class RedirectGuard implements CanActivate {


constructor(private router: Router) {}


canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {


window.location.href = route.data['externalUrl'];
return true;


}
}

导入 app.module:

providers: [RedirectGuard],

确定你的路线:

{
path: 'youtube',
canActivate: [RedirectGuard],
component: RedirectGuard,
data: {
externalUrl: 'https://www.youtube.com/'
}
}

您可以使用 导航结束事件。

从“@angle/Router”导入{ NavigationEnd,Router } ;

应用程序组件

this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
if (event.url.includes('faq')) {
// open in the same tab:
window.location.href = 'https://faq.website.com';


// open a new tab:
// window.open('https://faq.website.com', '_blank');


// and redirect the current page:
// this.router.navigate(['/']);
}
}
});

不要忘记从 AppRoutingModule 中删除你的路由。

使用:

{
path: 'external-link',
loadChildren: () => new Promise( () => { if(window.location.href.match(/external-link/) ) window.location.href = 'https://external-link.com/'; } )
},

这里有一个代码,它应该可以为您工作,没有很多问题。仅供参考,路由器事件错误处理程序可以放在任何位置,与组件的位置无关。

App.Component. html

Angular Port is in 4200
<a routerLink="/test">Main Link - 1</a> |


<a [routerLink]="getLinkWithExternal({url: '/test', external:false})">Other Link - 1a</a> |
<a [routerLink]="getLinkWithExternal({url: 'http://localhost:4211', external:true})">Other Link - 1b</a> |


<a [routerLink]="getLink({url: '/test'})">Other Link - 1a</a> |
<a [routerLink]="getLink({url: 'http://localhost:4211'})">Other Link - 1b</a> |




<a style="cursor: pointer; text-decoration: underline;" (click)="routeLink('/test')">Other Link - 1c</a> |
<a style="cursor: pointer; text-decoration: underline;" (click)="routeLink('http://localhost:4211')">Other Link - 1d</a>


<router-outlet></router-outlet>

应用程序组件

import { Component } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';


@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';


constructor(private router: Router) { }


// RECOMMENDATION - Add following in menus of each microservice (individual and different)
//    external: true
// Will make it a better menu structure for each microservice
// If Single and same menu for all microservices then remove external === true
// Logic One
getLinkWithExternal(sidebarnavLink: any) {
this.router.errorHandler = function (error: any) {
if (!sidebarnavLink.url.includes(window.location.origin.toString()) && sidebarnavLink.url.includes("http") && sidebarnavLink.external === true) {
window.location.href = sidebarnavLink.url.toString();
return true;
}
return null;
}.bind(sidebarnavLink);
return [sidebarnavLink.url];
}


getLinkWithExternalWithEventSubscribe(sidebarnavLink: any) {
this.router.events.subscribe(function (event) {
if (event instanceof NavigationEnd) {
if (event.url.includes('http')) {
if (!sidebarnavLink.url.includes(window.location.origin.toString()) && sidebarnavLink.url.includes("http") && sidebarnavLink.external === true) {
window.location.href = sidebarnavLink.url.toString();
return true;
}
return this.router.navigateByUrl(sidebarnavLink.url);
// return this.router.navigate([sidebarnavLink.url]);
}
return this.router.navigateByUrl(sidebarnavLink.url);
// return this.router.navigate([sidebarnavLink.url]);
}
}.bind(sidebarnavLink))
}


getLinkWithExternalImplementationTwoWithNoRouteError(sidebarnavLink: any) {
if (!sidebarnavLink.url.includes(window.location.origin.toString()) && sidebarnavLink.url.includes("http") && sidebarnavLink.external === true) {
window.location.href = sidebarnavLink.url.toString();
return true;
}
return [sidebarnavLink.url];
}


// Logic Two
getLink(sidebarnavLink: any) {
this.router.errorHandler = function (error: any) {
if (!sidebarnavLink.url.includes(window.location.origin.toString()) && sidebarnavLink.url.includes("http")) {
window.location.href = sidebarnavLink.url.toString();
return true;
}
return null;
}.bind(sidebarnavLink);
return [sidebarnavLink.url];
}


// Logic Three
routeLink(lnk: any) {
if (lnk.includes("http")) {
console.log("Test");
window.location.href = lnk;
return true;
}
return this.router.navigateByUrl(lnk);
// return this.router.navigate([lnk]);
}


}