【问题标题】:How to access a constant in an Angular 2 component and service?如何访问 Angular 2 组件和服务中的常量?
【发布时间】:2017-03-07 08:39:29
【问题描述】:

我有一个常量文件constants.ts

export const C0NST = "constant";

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

import { C0NST } from './constants';

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

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

some.component.ts

import { C0NST } from './constants';

some.component.html

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

但是在组件类中定义一个成员是可行的:

some.component.ts

public const constant = C0NST;

some.component.html

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

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

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

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

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


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

    【讨论】:

    • 谢谢霍里亚。我有一个需要从 Giphy 获取的 GIF URL 列表,因此我将这些 URL 保存在常量文件中。我打算在整个应用程序中跨组件使用这些。你认为有什么更好的方法?
    • @KabirRoy 这听起来确实不错。如果您的图像数量相对较少,您实际上可以为它们创建组件,并直接在源代码中使用 giphy URL(就像您为应用程序提供的资产所做的那样)。但这听起来是个好方法,无论如何。
    • 如何格式化字符串 "mm/dd/yyyy" 它们是遍历整个应用程序的,为什么它不应该在任何模板中访问?
    【解决方案2】:

    由于在组件的模板中只能使用组件类的属性,不能直接使用任何外部常量(或外部变量)。

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

    import { MY_CONSTANT } from '../constants';
    
    @Component({
      // ...
    })
    export class MyTestComponent implements OnInit {
    
      readonly MY_CONSTANT = MY_CONSTANT;
    
      // ...
    }
    

    这基本上只是在组件类中创建了一个新属性MY_CONSTANT。使用readonly,我们确保新属性不能被修改。

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

    {{ MY_CONSTANT }}
    

    【讨论】:

    • 这是正确的答案,但您应该添加static 以避免在构造函数中重新分配。所以它真的应该是:readonly myConstant = MY_CONSTANT; 另请注意关于常量语法的样式指南建议。
    【解决方案3】:

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

    您可以像这样提供它

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

    【讨论】:

    • 这有什么缺点吗?我在想,如果我 CONST 是一个枚举并且更改检测是 Push 应该没有。
    • @bhantol 我认为没有缺点。
    • 这不是一个常数。 myConst 可以重新分配。
    • @mrgoos CONST 是不变的。您不能直接在 Angular 绑定中访问 c​​onst 值(至少在我发布此答案时没有 - 不是最新的 Angular 开发)
    • @GünterZöchbauer- 它是恒定的,但 myConst 不是。可以在MyComponent类中修改。
    【解决方案4】:

    我认为有两个最好的方向:

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

    枚举.ts

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

    component.ts

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

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

    component.html

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

    此解决方案在内存使用情况下效率较低,因为您基本上是在您希望使用它的每个组件中复制数据(或对常量的引用)。除此之外,语法
    readonly constData: typeof constData = constData
    在我看来,这会引入很多语法噪音,可能会让新手感到困惑

    在组件函数中封装外部常量

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

    枚举.ts

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

    component.ts

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

    component.html

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

    好消息是控制器中的数据不会重复,但会出现其他主要缺点。根据 Angular 团队的说法,由于更改检测机制,不建议在模板中使用函数,这在函数将值返回到模板的情况下效率较低:更改检测不知道函数返回的值是否已更改,所以它会被调用的频率比需要的多(假设你从它返回const,它实际上只需要一次,在填充模板视图时。它可能只是对你的应用程序有一点效率影响(如果你幸运的话)或者它可能完全崩溃如果函数以Observable 解析,则将其关闭,并且您使用async 管道订阅结果。您可以参考我关于HERE 的短文

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-16
        • 2016-12-16
        • 2018-07-12
        • 1970-01-01
        • 1970-01-01
        • 2020-08-05
        相关资源
        最近更新 更多