如何在@Component 声明中使用服务或全局函数?

How can I use a service or global function in the @Component declaration?

我有一项服务可以帮助解决与我的环境相关的一些路由问题,现在我需要处理模板路由问题

理想情况下,我可以这样做:

import { PathSvc } from './globals/path.svc';
@Component({
    templateUrl: this.pathSvc.alias + '/app/my.comp.html'
})
export class MyComp {
    constructor(private pathSvc: PathSvc) { }           
}

当然这不起作用,因为该服务未在组件声明中使用,所以我收到运行时控制台错误:

requests:38 Error: TypeError: Cannot read property 'pathSvc' of undefined(…)

genaral 中的 Typescript 和模块化 JS 对我来说是新事物。也许有更直接的方法将我的函数导入到一堆模块中并在我想要的任何地方使用它?

我意识到这不是最佳方法,我应该使用

获得这些结果
<base href="/{alias}" />

方法论,但现在还没有发生。

简而言之,当我试图让我的 ASP.Net MVC + Angular 2 应用程序更动态地了解其托管环境并处理后端和前端时,所有这些都停止了工作路由冲突。我想让它在更多 "right way" 中工作,但目前,我只需要它工作,这样我的老板就会很高兴,而全局路由脚本似乎就是这种方式。

如果我没理解错的话,你想创建一个服务,作为 angular 的 DI 进程的助手。

就像@Günter_Zöchbauer 所说的那样,Injectable 不能在 Ng2 对象(Component、Injectable...)的实例之外使用,但在您的情况下,创建一个 injectable 是无关紧要的。 创建一个angular应用并不意味着你所有的文件都必须包含angular对象,你也可以创建基本的classes/constants..

例如,如果您想要一个为您构建 url 的助手,您可以创建一个 class 并通过导入它在组件声明中使用它。

//urlbuilder.ts
const host:string = 'http://foo.bar.com';
export class UrlBuilder {
    static generate(file:string = '') {
        return host + file;
    }
}

// component.ts
import {UrlBuilder} from './urlbuilder';

@Component({
    templateUrl: UrlBuilder.generate('/foo.html')
})
export class FooComponent {}

您甚至可以导出函数而不是 class,它也可以工作。 以下代码显示与上面相同的代码,但带有一个函数和一个 es6 标记。

//urlbuilder.ts
const host:string = 'http://foo.bar.com';
export const UrlBuilder = urlBuilderFn;

//basic tag function that build a template string with potential variables
function urlBuilderFn(strs, ...raws) {
    let builtStr = '', length = strs.length;

    for(let i = 0; i < length; i++)
        builtStr = strs[i] + (raws[i] !== undefined && raws[i] !== null ? raws[i] : '');

    return host + builtStr;
}


// component.ts
import {UrlBuilder as url} from './urlbuilder';

@Component({
    templateUrl: url`/foo.html`
})
export class FooComponent {}

但是,如果你也想将你的助手与 DI 一起使用(无论出于何种原因,需要 angular deps..)你可以使用静态方法制作可注射的 class。

//urlbuilder.ts
const host:string = 'http://foo.bar.com';

@Injectable()
export class UrlBuilder {

    constructor(private http:Http) {}

    static generate(file:string = '') {
        return host + file;
    }

    doSomething() {
        return this.http.get(UrlBuilder.generate('/foo/bar'))
    }
}

// component.ts
import {UrlBuilder} from './urlbuilder';

@Component({
    templateUrl: UrlBuilder.generate('/foo.html')
})
export class FooComponent {

    constructor(private builder:UrlBuilder) {}

    ngOnInit() {
        this.builder.doSomething()
    }

}

另一方面,如果您唯一的问题是模板,为什么不直接将它们写成模板字符串或直接使用您的任务管理器 (webpack..) 导入它们。通常,如果您没有动态视图,因此必须从您的服务器生成它们,最好避免通过 http 调用来检索它们并将它们直接加载到 javascript 文件中。

我已经处理了这个问题,我通过在我的 configuration/appSettings 中设置 baseHref 来解决它。使 Angular 页面容器成为 .ASPX 页面,在页面加载时,从配置中设置 baseHref。这是我 Web.config:

的片段
<appSettings>
  <add key="AppBaseUrl" value="/MyAngularApp/" />
</appSettings>

这里是使您的 Angular 应用程序在 IIS 中托管时正常运行的重写规则:

<rewrite>
  <rules>
    <rule name="Rewrite Index to Root" stopProcessing="true" enabled="true">
      <match url=".*" />
      <conditions>
          <add input="{URL}" pattern="^(.*)(/index.aspx)$" />
      </conditions>
      <action type="Redirect" url="{C:1}" />
    </rule>
    <rule name="Angular" stopProcessing="true" enabled="true">
      <match url="^(.*)$" ignoreCase="false" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="index.aspx/{R:0}" appendQueryString="true" />
    </rule>
  </rules>
</rewrite>