【问题标题】:How to get base url in angular 5?如何在角度 5 中获取基本 url?
【发布时间】:2019-01-29 17:49:35
【问题描述】:

我当前的网址是http://localhost:4200/test/dashboard

我想使用 Angular 5 功能打印基本网址,即http://localhost:4200

【问题讨论】:

标签: angular angular5


【解决方案1】:

这里的其他答案涵盖了相当多的选项:

  • location
  • window.location
  • document.location
  • DOCUMENT / Document
  • Location
  • LocationStrategy
  • PlatformLocation

TLDR; 对于简单的情况,全球可用的 DOM location 可能足以满足您的需求。但是,您可能真的想要一个 Angular Location 实例。而且,在某些情况下,LocationStrategy 也可能有用。

您可以直接访问 DOM location 而无需导入任何内容:

foo(): void {
  console.log(location.origin);
  console.log(location.href);
  console.log(location.pathname);
}

如果您想使用 Angular LocationLocationStrategy,那么您必须像这样将它们拉入:

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. locationwindow.locationdocument.location 的类型为 Location,直接来自 DOM,可作为全局变量使用,即您不必导入或以任何方式注入它们。

这些都是达到同一目的的所有方法。 locationwindow.location 字面上是同一个东西(window 可以显式引用,但它也是隐式全局 this)。 locationdocument.location本质上是一回事,请参阅 SO answer 了解更多详情。

您可以找到 Location here 的 MDN 文档。

所以如果 DOM Location 是你想要的,我会使用 location。有些人喜欢明确表示他们正在访问window 对象,并且更喜欢使用window.locationdocumentlocation 字段有一段令人困惑的历史,似乎是访问 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 实体 - LocationLocationStrategyPlatformLocation

令人困惑的是,Angular 使用与上面的 location 等类型相同的名称作为其位置类型(即Location)。 DOM Location 全局可用,不需要导入,Angular Location 需要从@angular/common 导入。

Angular 实体LocationLocationStrategyLocationStrategy 相互叠加,Location 包含LocationStrategyLocationStrategy 又包含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 中运行良好。

基本 href 和 Location

如果您有一个没有路由的简单应用程序,并且您将基本 href 设置为 / 以外的其他值,那么您可能会发现像 prepareExternalUrl 这样的函数无法考虑基本 href。如果您没有在app.module.tsimports 部分中包含RouterModule,则会发生这种情况。无论出于何种原因,Location 下的LocationStrategyPlatformLocation 仅在导入RouterModule 时才正确配置。要解决这个问题,只需添加以下内容:

imports: [
  ...
  RouterModule.forRoot([]),
  ...
]

即使您没有指定路由,即传入[],这也会正确配置一些东西以考虑您的基本href。

APP_BASE_HREFPlatformLocationLocation

在某些示例中,您会看到它声明您必须显式配置 APP_BASE_HREF 才能获取您的基本 href。例如。就像app.module.ts

providers: [{
  provide: APP_BASE_HREF,
  useFactory: (pl: PlatformLocation) => pl.getBaseHrefFromDOM(),
  deps: [PlatformLocation]
}]

这个可能在某个阶段是必要的,但当前的PathLocationStrategy 代码会自动为您执行此操作,即如果您不设置APP_BASE_HREF,那么它会自行检索基本 href 值使用PathLocationStrategygetBaseHrefFromDOM() 方法。你可以在PathLocationStrategyconstructor逻辑中看到这个here

【讨论】:

  • 迄今为止我读过的关于整个基本 href 主题的最佳解释和总结。为我解决了许多问题。非常感谢。
  • 我给你竖起大拇指。如何在 SSR 中实现同样的东西
【解决方案2】:

不需要特定角度的功能,window.location.origin 会为您完成。

【讨论】:

  • 这个答案对于大多数情况来说可能是完美的。但是,如果您已将基本 href 设置为 / 以外的其他内容,或者您​​需要支持更复杂的情况,那么还有很多附加选项。有关这些的详细信息,请参阅this answer
【解决方案3】:

console.log(位置);

console.log(location.href);

获取基本网址:console.log(location.origin);

【讨论】:

    【解决方案4】:

    这对我不起作用(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;
    }
    

    【讨论】:

      【解决方案5】:

      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 的目的。如果 Angular 不在浏览器中运行,这将中断。
      • documentation for PlatformLocation 表示“不应由应用程序开发人员直接使用。而应使用 Location。”请参阅my answer 了解Location 以及一系列替代方案。
      【解决方案6】:
      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()}`
        }
      
      }
      

      【讨论】:

        【解决方案7】:

        我使用了 Rotemya 的回答中的位置,如下所示

        import { Location } from '@angular/common';
        
        constructor(public location: Location) { }
        

        但是 this.location.origin 对我不起作用。所以我使用了this.location.path.name

         ngOnInit() {
                console.log(this.location.path.name);
          }
        

        【讨论】:

          【解决方案8】:

          您可以尝试(可以获取当前位置的所有详细信息)

          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);  
              }
          }
          

          【讨论】:

            【解决方案9】:

            您可以从“通用”包中导入“位置”:

            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
              }
            
            }
            

            【讨论】:

            • 此位置对象中没有“原点”
            • 该类的属性来源不存在。
            猜你喜欢
            • 2019-08-08
            • 2018-11-25
            • 1970-01-01
            • 2014-02-10
            • 1970-01-01
            • 2011-11-22
            • 2020-01-15
            • 2020-04-24
            相关资源
            最近更新 更多