如何访问Angular 2组件和服务中的常量?

Kar*_*yal 49 typescript angular

我有一个常量文件constants.ts:

export const C0NST = "constant";
Run Code Online (Sandbox Code Playgroud)

我在some.service.ts服务中访问它,如下所示:

import { C0NST } from './constants';

console.log(C0NST); // "constant"
Run Code Online (Sandbox Code Playgroud)

但是,当我在组件模板中访问它时:

some.component.ts:

import { C0NST } from './constants';
Run Code Online (Sandbox Code Playgroud)

some.component.html:

{{ C0NST }} <!-- Outputs nothing -->
Run Code Online (Sandbox Code Playgroud)

但是,在组件类中定义成员有效:

some.component.ts

public const constant = C0NST;
Run Code Online (Sandbox Code Playgroud)

some.component.html

{{ constant }} <!-- constant -->
Run Code Online (Sandbox Code Playgroud)

我不明白为什么我能够直接在服务类中访问导入的常量,但不能在组件模板中访问,即使我在组件类中导入它.

Hor*_*man 47

在Angular2中,模板只能访问组件类的字段和方法.其他一切都是禁区.这包括组件类可见的内容.

解决这个问题的方法是在组件内部有一个字段,它只引用常量,然后使用它.


这是设计的一个限制,但也许您应该更多地了解为什么首先需要模板中的常量.通常这些东西由组件本身或服务使用,但不是模板.

  • 格式化字符串“mm/dd/yyyy”怎么样?它们遍历整个应用程序,为什么它不应该在任何模板中访问? (4认同)
  • @KabirRoy 这听起来实际上是一件不错的事情。如果您的图像数量相对较少,您实际上可以为它们创建组件,并直接在源中使用 giphy URL(就像您对应用程序提供的资产所做的那样)。但无论如何,这听起来都是一个不错的方法。 (2认同)

Fra*_*rzi 26

因为在Component的模板中你只能使用Component类的属性,所以不能直接使用任何外部常量(或外部变量).

到目前为止我发现的最优雅的方式如下:

import { MY_CONSTANT } from '../constants';

@Component({
  // ...
})
export class MyTestComponent implements OnInit {

  readonly MY_CONSTANT = MY_CONSTANT;

  // ...
}
Run Code Online (Sandbox Code Playgroud)

这基本上只是MY_CONSTANT在组件类中创建一个新属性.使用readonly,我们确保无法修改新属性.

这样,您可以在模板中使用:

{{ MY_CONSTANT }}

  • 这是正确的答案,但您应该添加 `static` 以避免在构造函数中重新分配。所以它真的应该是:`readonly myConstant = MY_CONSTANT;` 请注意常量语法的样式指南建议。 (5认同)

Gün*_*uer 19

Angular2模板绑定的范围是组件实例.只有那里可以访问的内容才能用于绑定.

你可以像它一样使用它

class MyComponent {
  myConst = CONST;
}
Run Code Online (Sandbox Code Playgroud)
{{myConst}}
Run Code Online (Sandbox Code Playgroud)

  • @bhantol 我不认为有缺点。 (2认同)

Tom*_*mas 11

我认为有两个最佳方向:

将常量包装为内部组件属性

enum.ts

export enum stateEnum {
  'DOING' = 0,
  'DONE',
  'FAILED'
}
Run Code Online (Sandbox Code Playgroud)

component.ts

import { stateEnum  } from './enum'
export class EnumUserClass {
  readonly stateEnum : typeof stateEnum = stateEnum ;    
}
Run Code Online (Sandbox Code Playgroud)

示例使用枚举,但这可以是任何类型的已定义常量.typeof运算符为您提供TypeScript输入功能的所有好处.您可以直接在模板中使用此变量:

component.html

<p>{{stateEnum.DOING}}<p>
Run Code Online (Sandbox Code Playgroud)

此解决方案在内存使用上下文中效率较低,因为您基本上在要使用它的每个组件中复制数据(或对常量的引用).除此之外,
readonly constData: typeof constData = constData
我认为语法会引入很多语法噪音,并且可能会让新用户感到困惑

在组件功能中包装外部常量

第二个选项是使用组件函数包装外部变量/常量并在模板上使用该函数:

enum.ts

export enum stateEnum {
  'DOING' = 0,
  'DONE',
  'FAILED'
}
Run Code Online (Sandbox Code Playgroud)

component.ts

import { stateEnum  } from './enum'
export class EnumUserClass {
  getEnumString(idx) {
    return stateEnum[stateEnum[idx]];
  }   
}
Run Code Online (Sandbox Code Playgroud)

component.html

<p>{{getEnumString(1)}}</p>  
Run Code Online (Sandbox Code Playgroud)

好的是数据不会在控制器中重复,但会出现其他主要缺点.根据Angular团队的说法,由于更改检测机制,建议不要使用模板中的函数,如果函数将值返回到模板,则效率会降低:更改检测不知道函数的值返回是否已更改,因此它将通常被称为方式而不是需要(假设你const从它返回,它实际上只需要一次,当填充模板视图.它可能只是一点效率杀死你的应用程序(如果你很幸运)或它可能完全打破它,如果函数解析,Observable例如,你使用async管道来订阅结果.你可以参考我在这里的短文


ser*_*anD 5

你可以创建一个 BaseComponent ,它是你应该创建常量实例的地方,然后你可以创建你的 FooComponent extends BaseComponent 并且你可以使用你的常量。