【发布时间】:2019-01-29 17:49:35
【问题描述】:
我当前的网址是http://localhost:4200/test/dashboard。
我想使用 Angular 5 功能打印基本网址,即http://localhost:4200。
【问题讨论】:
我当前的网址是http://localhost:4200/test/dashboard。
我想使用 Angular 5 功能打印基本网址,即http://localhost:4200。
【问题讨论】:
这里的其他答案涵盖了相当多的选项:
locationwindow.locationdocument.locationDOCUMENT / Document
LocationLocationStrategyPlatformLocationTLDR; 对于简单的情况,全球可用的 DOM location 可能足以满足您的需求。但是,您可能真的想要一个 Angular Location 实例。而且,在某些情况下,LocationStrategy 也可能有用。
您可以直接访问 DOM location 而无需导入任何内容:
foo(): void {
console.log(location.origin);
console.log(location.href);
console.log(location.pathname);
}
如果您想使用 Angular Location 和 LocationStrategy,那么您必须像这样将它们拉入:
import { Location, LocationStrategy } from '@angular/common';
constructor(private location: Location, private locationStrategy: LocationStrategy) { }
foo(): void {
console.log(this.location.path());
console.log(this.location.prepareExternalUrl('/'));
console.log(this.locationStrategy.getBaseHref());
}
您可以使用prepareExternalUrl 来表示,例如构建引用资产的 URL:
const url = this.location.prepareExternalUrl('assets/svg/icons.svg');
如果您直接在 / 下提供所有内容,则使用 Angular Location 似乎没有多大意义,但如果您已将应用程序的基本 href 设置为 / 或如果您正在使用路径做更复杂的事情,那么 Angular Location 将帮助您正确处理此类事情。
如果 prepareExternalUrl 似乎没有选择您的基本 href,请参阅此答案末尾的相关说明。
在某些示例中,您会看到它声明您必须配置APP_BASE_HREF 才能获取您的基本href。现在不再是这种情况了,有关更多信息,请参阅此答案的结尾。
注意:默认情况下,Angular 使用定位策略PathLocationStrategy,但如果您更改为使用HashLocationStrategy,那么prepareExternalUrl 和其他功能将无法以相同的方式工作。但是,如果您使用的是HashLocationStrategy,您可能知道自己在做什么,所以我不会在这里讨论。
让我们依次看看上面列出的每个实体。
1. location、window.location 和 document.location 的类型为 Location,直接来自 DOM,可作为全局变量使用,即您不必导入或以任何方式注入它们。
这些都是达到同一目的的所有方法。 location 和 window.location 字面上是同一个东西(window 可以显式引用,但它也是隐式全局 this)。 location 和 document.location本质上是一回事,请参阅 SO answer 了解更多详情。
您可以找到 Location here 的 MDN 文档。
所以如果 DOM Location 是你想要的,我会使用 location。有些人喜欢明确表示他们正在访问window 对象,并且更喜欢使用window.location。 document 的 location 字段有一段令人困惑的历史,似乎是访问 DOM Location 实例的最不流行的方式。
2. 在其他地方,您可以看到人们使用 Angular 依赖注入令牌 DOCUMENT,如下所示:
import { DOCUMENT } from '@angular/common';
import { Inject } from '@angular/core';
constructor(@Inject(DOCUMENT) private document: Document)
然后您可以访问this.document.location。同样,这只是一个 DOM Location 实例,所以如果这是您想要的,当您可以直接以 location 访问它时,为什么还要麻烦注入它呢?上面提到的this.document 和全局可用的document 都是Document 类型,并且在浏览器上下文中,它们是同一个东西。因此,您注入它的唯一原因是您在非浏览器上下文中工作。
您可以找到 DOCUMENT here 的 Angular 文档和 Document here 的 MDN 文档。
3. 最后三个 Angular 实体 - Location、LocationStrategy 和 PlatformLocation。
令人困惑的是,Angular 使用与上面的 location 等类型相同的名称作为其位置类型(即Location)。 DOM Location 全局可用,不需要导入,Angular Location 需要从@angular/common 导入。
Angular 实体Location、LocationStrategy 和LocationStrategy 相互叠加,Location 包含LocationStrategy,LocationStrategy 又包含PlatformLocation。它们都没有直接暴露包含的实体,即您无法通过Location API 访问LocationStrategy,也无法通过LocationStrategy 访问PlatformLocation。
您会看到许多直接访问 PlatformLocation 的旧示例,但正如其 documentation 所明确指出的那样,这个“类应该不由应用程序开发人员直接使用。”
所以我们从一个令人困惑的实体数组开始,但最后,它实际上只是归结为在 DOM 提供的全局 location 对象和 Angular 提供的 Location 对象之间进行选择。在某些情况下,LocationStrategy 也可能感兴趣。
但是,如果您想要更深入地了解,为什么不试试下面的代码,它会引入提到的每一个实体。查看控制台输出以查看每个实体提供的内容,并尝试使用每个实体的 API。为简单起见,只需将此代码添加到现有组件之一:
import { Inject } from '@angular/core';
import { DOCUMENT, Location, LocationStrategy, PlatformLocation } from '@angular/common';
// Normally, you should not access PlatformLocation directly, it's just included here for completeness.
constructor(@Inject(DOCUMENT) private document: Document, private location: Location, private locationStrategy: LocationStrategy, private plaformLocation: PlatformLocation) { }
ngOnInit(): void {
// These are just different ways to get the same thing, so if this
// is what want, you might as well use plain location directly.
console.log('DOM location', location)
console.log('DOM window.location', window.location)
console.log('DOM document.location', document.location)
console.log('Injected document.location', this.document.location)
// These are layered on top of each other. A Location contains a
// LocationStrategy and a LocationStrategy contains a PlatformLocation.
// Note that this.location, used here, is a different thing to plain location above.
console.log('location', this.location)
console.log('locationStrategy', this.locationStrategy)
console.log('platformLocation', this.plaformLocation) // PlatformLocation "should not be used directly by an application developer."
}
在浏览器中打开您的应用,然后查看开发人员工具中的控制台输出,看看您是否找到了所需的内容。
注意:在 Angular 世界中,事情很快就会变得陈旧 - 以上都在 Angular 9 中运行良好。
Location
如果您有一个没有路由的简单应用程序,并且您将基本 href 设置为 / 以外的其他值,那么您可能会发现像 prepareExternalUrl 这样的函数无法考虑基本 href。如果您没有在app.module.ts 的imports 部分中包含RouterModule,则会发生这种情况。无论出于何种原因,Location 下的LocationStrategy 和PlatformLocation 仅在导入RouterModule 时才正确配置。要解决这个问题,只需添加以下内容:
imports: [
...
RouterModule.forRoot([]),
...
]
即使您没有指定路由,即传入[],这也会正确配置一些东西以考虑您的基本href。
APP_BASE_HREF、PlatformLocation 和 Location
在某些示例中,您会看到它声明您必须显式配置 APP_BASE_HREF 才能获取您的基本 href。例如。就像app.module.ts:
providers: [{
provide: APP_BASE_HREF,
useFactory: (pl: PlatformLocation) => pl.getBaseHrefFromDOM(),
deps: [PlatformLocation]
}]
这个可能在某个阶段是必要的,但当前的PathLocationStrategy 代码会自动为您执行此操作,即如果您不设置APP_BASE_HREF,那么它会自行检索基本 href 值使用PathLocationStrategy 的getBaseHrefFromDOM() 方法。你可以在PathLocationStrategy的constructor逻辑中看到这个here。
【讨论】:
不需要特定角度的功能,window.location.origin 会为您完成。
【讨论】:
/ 以外的其他内容,或者您需要支持更复杂的情况,那么还有很多附加选项。有关这些的详细信息,请参阅this answer。
console.log(位置);
console.log(location.href);
获取基本网址:console.log(location.origin);
【讨论】:
这对我不起作用(Angular 7):
this.location.path.name
但我发现可以从文档中获取:
import { Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
constructor(@Inject(DOCUMENT) private document: Document) {
const origin = this.document.location.origin;
}
【讨论】:
PlatformLocation 提供有关 URL 的更多详细信息:
import {PlatformLocation } from '@angular/common';
constructor(platformLocation: PlatformLocation) {
console.log((platformLocation as any).location);
console.log((platformLocation as any).location.href);
console.log((platformLocation as any).location.origin);
}
【讨论】:
PlatformLocation 表示“不应由应用程序开发人员直接使用。而应使用 Location。”请参阅my answer 了解Location 以及一系列替代方案。
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT, LocationStrategy } from '@angular/common';
@Injectable()
export class UrlService {
constructor(
@Inject(DOCUMENT) private readonly document: Document,
private readonly locationStrategy: LocationStrategy
) {}
// example for localhost: http://localhost:4200/someBaseHref
getUrl(): string {
return `${this.document.location.origin}/${this.locationStrategy.getBaseHref()}`
}
}
【讨论】:
我使用了 Rotemya 的回答中的位置,如下所示
import { Location } from '@angular/common';
constructor(public location: Location) { }
但是 this.location.origin 对我不起作用。所以我使用了this.location.path.name
ngOnInit() {
console.log(this.location.path.name);
}
【讨论】:
您可以尝试(可以获取当前位置的所有详细信息)
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
@Component({
selector: 'some-component',
templateUrl: './component.html',
styleUrls: ['./component.scss']
})
export class SomeComponent implements OnInit {
constructor(location: Location) {}
ngOnInit() {
console.log(this.location._platformStrategy._platformLocation.location);
}
}
【讨论】:
您可以从“通用”包中导入“位置”:
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common'; // <--- Here
import { Router } from '@angular/router';
@Component({
selector: 'some-component',
templateUrl: './component.html',
styleUrls: ['./component.scss']
})
export class SomeComponent implements OnInit {
constructor(location: Location) {}
ngOnInit() {
console.log(this.location.origin); // <--- Use Here
}
}
【讨论】: