简体   繁体   English

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

[英]How to access a constant in an Angular 2 component and service?

I have a constants file constants.ts :我有一个常量文件constants.ts

export const C0NST = "constant";

I access it in a service some.service.ts like so:我在服务some.service.ts 中访问它,如下所示:

import { C0NST } from './constants';

console.log(C0NST); // "constant"

However, when I access it in a component template:但是,当我在组件模板中访问它时:

some.component.ts : some.component.ts

import { C0NST } from './constants';

some.component.html : some.component.html

{{ C0NST }} <!-- Outputs nothing -->

However defining a member in the component class works:但是在组件类中定义一个成员是有效的:

some.component.ts some.component.ts

public const constant = C0NST;

some.component.html some.component.html

{{ constant }} <!-- constant -->

I don't understand why I was able to access the imported constant directly in the service class but not in the component template even though I imported it in the component class.我不明白为什么我能够直接在服务类中访问导入的常量,但不能在组件模板中访问,即使我在组件类中导入了它。

In Angular2, the template can only access fields and methods of the component class.在 Angular2 中,模板只能访问组件类的字段和方法。 Everything else is off-limits.其他一切都是禁区。 This includes things which are visible to the component class.这包括组件类可见的内容。

The way to go around this is to have a field inside the component, which just references the constant, and use that instead.解决这个问题的方法是在组件内部有一个字段,它只引用常量,然后使用它。


It's one limitation of the design, but perhaps you should think a bit more about why you need a constant in the template in the first place.这是设计的一个限制,但也许您应该首先考虑一下为什么需要在模板中使用常量。 Usually these things are used by components themselves, or services, but not the template.通常这些东西是由组件本身或服务使用的,而不是模板使用的。

Since in the Component's template you can only use attributes of the Component's class, you can't directly use any external constants (or external variables).由于在组件的模板中只能使用组件类的属性,不能直接使用任何外部常量(或外部变量)。

The most elegant way that I've found so far is the following:到目前为止,我发现的最优雅的方法如下:

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

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

  readonly MY_CONSTANT = MY_CONSTANT;

  // ...
}

which basically just creates a new attribute MY_CONSTANT inside the component class.它基本上只是在组件类中创建了一个新属性MY_CONSTANT Using readonly we make sure that the new attribute cannot be modified.使用readonly我们确保不能修改新属性。

Doing so, in your template you can now use:这样做,您现在可以在模板中使用:

{{ MY_CONSTANT }}

The scope of Angular2 template bindings is the component instance. Angular2 模板绑定的范围是组件实例。 Only what's accessible there can be used in bindings.只有在那里可以访问的内容才能用于绑定。

You can make it available like你可以让它像

class MyComponent {
  myConst = CONST;
}
{{myConst}}

There are two best directions in my opinion:我认为最好的方向有两个:

Wrapping constants as internal component property将常量包装为内部组件属性

enum.ts枚举

export enum stateEnum {
  'DOING' = 0,
  'DONE',
  'FAILED'
}

component.ts组件.ts

import { stateEnum  } from './enum'
export class EnumUserClass {
  readonly stateEnum : typeof stateEnum = stateEnum ;    
}

Example uses enum, but this can be any type of defined constant.示例使用枚举,但这可以是任何类型的定义常量。 typeof operator gives you all of benefits of TypeScript typing features. typeof运算符为您提供 TypeScript 类型功能的所有好处。 You can use then this variable directly in templates:您可以直接在模板中使用此变量:

component.html组件.html

<p>{{stateEnum.DOING}}<p>

This solution is less efficient in memory usage context, because you are basically duplicating data (or references to constants) in each component you wish to use it.此解决方案在内存使用上下文中效率较低,因为您基本上是在希望使用它的每个组件中复制数据(或对常量的引用)。 Beside that, syntax除此之外,语法
readonly constData: typeof constData = constData
in my opinion introduce a lot of syntax noise and may be confusing to newcommers在我看来,引入了很多语法噪音,可能会让新手感到困惑

Wrapping external constant in component function在组件函数中包装外部常量

Second option is to wrap your external variable/constant with component function and use that function on template:第二种选择是用组件函数包装外部变量/常量并在模板上使用该函数:

enum.ts枚举

export enum stateEnum {
  'DOING' = 0,
  'DONE',
  'FAILED'
}

component.ts组件.ts

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

component.html组件.html

<p>{{getEnumString(1)}}</p>  

Good thing is that data is not duplicated in controller but other major downside occur.好消息是数据不会在控制器中重复,但会出现其他主要缺点。 According to Angular team, usage of functions in templates is not recommended due to change detection mechanism, which works way less efficient in case of functions returning values to templates: change detection have no idea does value return by a function has changed, so it will be called way often than needed (and assuming you returning const from it, it's actually needed only once, when populating template view. It may be just a bit efficiency killing to your application (if you are lucky) or it may totally break it down if function resolves with Observable for instance, and you use async pipe to subscribe to results. You can refer to my short article on that HERE根据 Angular 团队的说法,不建议在模板中使用函数,因为更改检测机制在函数返回值到模板的情况下效率较低:更改检测不知道函数返回的值是否已更改,因此它会经常被调用(假设你从它返回const ,它实际上只需要一次,在填充模板视图时。它可能只是你的应用程序的一点效率(如果你很幸运)或者它可能完全破坏它例如,如果函数使用Observable解析,并且您使用async管道订阅结果。您可以参考我关于该内容的简短文章HERE

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM